summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opentracker.c91
-rw-r--r--trackerlogic.c110
-rw-r--r--trackerlogic.h12
3 files changed, 114 insertions, 99 deletions
diff --git a/opentracker.c b/opentracker.c
index 7be1421..0ddce0c 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -56,6 +56,7 @@ struct http_data {
56 io_batch batch; 56 io_batch batch;
57 }; 57 };
58 unsigned char ip[4]; 58 unsigned char ip[4];
59 int blessed;
59}; 60};
60 61
61/* Prototypes */ 62/* Prototypes */
@@ -87,6 +88,7 @@ static void graceful( int s );
87#define HTTPERROR_400 return httperror( s, "400 Invalid Request", "This server only understands GET." ) 88#define HTTPERROR_400 return httperror( s, "400 Invalid Request", "This server only understands GET." )
88#define HTTPERROR_400_PARAM return httperror( s, "400 Invalid Request", "Invalid parameter" ) 89#define HTTPERROR_400_PARAM return httperror( s, "400 Invalid Request", "Invalid parameter" )
89#define HTTPERROR_400_COMPACT return httperror( s, "400 Invalid Request", "This server only delivers compact results." ) 90#define HTTPERROR_400_COMPACT return httperror( s, "400 Invalid Request", "This server only delivers compact results." )
91#define HTTPERROR_403_IP return httperror( s, "403 Access Denied", "Your ip address is not allowed to administrate this server." )
90#define HTTPERROR_404 return httperror( s, "404 Not Found", "No such file or directory." ) 92#define HTTPERROR_404 return httperror( s, "404 Not Found", "No such file or directory." )
91#define HTTPERROR_500 return httperror( s, "500 Internal Server Error", "A server error has occured. Please retry later." ) 93#define HTTPERROR_500 return httperror( s, "500 Internal Server Error", "A server error has occured. Please retry later." )
92 94
@@ -173,6 +175,7 @@ static void senddata( const int64 s, char *buffer, size_t size ) {
173} 175}
174 176
175static void httpresponse( const int64 s, char *data ) { 177static void httpresponse( const int64 s, char *data ) {
178 struct http_data* h = io_getcookie( s );
176 char *c, *reply; 179 char *c, *reply;
177 ot_peer peer; 180 ot_peer peer;
178 ot_torrent *torrent; 181 ot_torrent *torrent;
@@ -198,11 +201,48 @@ static void httpresponse( const int64 s, char *data ) {
198 for( c = data+4; *c == '/'; ++c); 201 for( c = data+4; *c == '/'; ++c);
199 202
200 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { 203 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
204
205/******************************
206 * S Y N C *
207 ******************************/
201 case 4: /* sync ? */ 208 case 4: /* sync ? */
202 if( byte_diff( data, 4, "sync") ) HTTPERROR_404; 209 if( byte_diff( data, 4, "sync") ) HTTPERROR_404;
203 if( !( reply_size = return_changeset_for_tracker( &reply ) ) ) HTTPERROR_500; 210 if( !h->blessed ) HTTPERROR_403_IP;
204 return sendmallocdata( s, reply, reply_size ); 211
212 mode = SYNC_OUT;
213 scanon = 1;
205 214
215 while( scanon ) {
216 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
217 case -2: scanon = 0; break; /* TERMINATOR */
218 case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
219 default: scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); break;
220 case 9:
221 if(byte_diff(data,9,"changeset")) {
222 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
223 continue;
224 }
225 /* ignore this, when we dont at least see "d4:syncdee" */
226 if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) < 10 ) HTTPERROR_400_PARAM;
227 if( add_changeset_to_tracker( (ot_byte*)data, len ) ) HTTPERROR_400_PARAM;
228 mode = SYNC_IN;
229 break;
230 }
231 }
232
233 if( mode == SYNC_OUT ) {
234 if( !( reply_size = return_changeset_for_tracker( &reply ) ) ) HTTPERROR_500;
235 return sendmallocdata( s, reply, reply_size );
236 }
237
238 /* Simple but proof for now */
239 reply = "OK";
240 reply_size = 2;
241
242 break;
243/******************************
244 * S T A T S *
245 ******************************/
206 case 5: /* stats ? */ 246 case 5: /* stats ? */
207 if( byte_diff(data,5,"stats")) HTTPERROR_404; 247 if( byte_diff(data,5,"stats")) HTTPERROR_404;
208 scanon = 1; 248 scanon = 1;
@@ -260,8 +300,11 @@ static void httpresponse( const int64 s, char *data ) {
260 if( !( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, mode ) ) ) HTTPERROR_500; 300 if( !( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, mode ) ) ) HTTPERROR_500;
261 break; 301 break;
262 } 302 }
263
264 break; 303 break;
304
305/******************************
306 * S C R A P E *
307 ******************************/
265 case 6: /* scrape ? */ 308 case 6: /* scrape ? */
266 if( byte_diff( data, 6, "scrape") ) HTTPERROR_404; 309 if( byte_diff( data, 6, "scrape") ) HTTPERROR_404;
267 310
@@ -280,7 +323,7 @@ SCRAPE_WORKAROUND:
280 } 323 }
281 /* ignore this, when we have less than 20 bytes */ 324 /* ignore this, when we have less than 20 bytes */
282 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; 325 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
283 hash = (ot_hash*)data; /* Fall through intended */ 326 hash = (ot_hash*)data;
284 break; 327 break;
285 } 328 }
286 } 329 }
@@ -297,6 +340,9 @@ SCRAPE_WORKAROUND:
297 340
298 ot_overall_tcp_successfulannounces++; 341 ot_overall_tcp_successfulannounces++;
299 break; 342 break;
343/******************************
344 * A N N O U N C E *
345 ******************************/
300 case 8: 346 case 8:
301 if( byte_diff( data, 8, "announce" ) ) HTTPERROR_404; 347 if( byte_diff( data, 8, "announce" ) ) HTTPERROR_404;
302 348
@@ -384,7 +430,7 @@ ANNOUNCE_WORKAROUND:
384 remove_peer_from_torrent( hash, &peer ); 430 remove_peer_from_torrent( hash, &peer );
385 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM ); 431 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM );
386 } else { 432 } else {
387 torrent = add_peer_to_torrent( hash, &peer ); 433 torrent = add_peer_to_torrent( hash, &peer, 0 );
388 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; 434 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500;
389 } 435 }
390 ot_overall_tcp_successfulannounces++; 436 ot_overall_tcp_successfulannounces++;
@@ -438,12 +484,6 @@ static void graceful( int s ) {
438 484
439static void usage( char *name ) { 485static void usage( char *name ) {
440 fprintf( stderr, "Usage: %s [-i serverip] [-p serverport] [-d serverdirectory]" 486 fprintf( stderr, "Usage: %s [-i serverip] [-p serverport] [-d serverdirectory]"
441#ifdef WANT_CLOSED_TRACKER
442 " [-oc]"
443#endif
444#ifdef WANT_BLACKLIST
445 " [-bB]"
446#endif
447 "\n", name ); 487 "\n", name );
448} 488}
449 489
@@ -453,23 +493,6 @@ static void help( char *name ) {
453 "\t-p serverport\tspecify tcp port to bind to (default: 6969, you may specify more than one)\n" 493 "\t-p serverport\tspecify tcp port to bind to (default: 6969, you may specify more than one)\n"
454 "\t-P serverport\tspecify udp port to bind to (default: 6969, you may specify more than one)\n" 494 "\t-P serverport\tspecify udp port to bind to (default: 6969, you may specify more than one)\n"
455 "\t-d serverdir\tspecify directory containing white- or black listed torrent info_hashes (default: \".\")\n" 495 "\t-d serverdir\tspecify directory containing white- or black listed torrent info_hashes (default: \".\")\n"
456#ifdef WANT_CLOSED_TRACKER
457 "\t-o\t\tmake tracker an open tracker, e.g. do not check for white list (default: off)\n"
458 "\t-c\t\tmake tracker a closed tracker, e.g. check each announced torrent against white list (default: on)\n"
459#endif
460#ifdef WANT_BLACKLIST
461 "\t-b\t\tmake tracker check its black list, e.g. check each announced torrent against black list (default: on)\n"
462 "\t-B\t\tmake tracker check its black list, e.g. check each announced torrent against black list (default: off)\n"
463#endif
464#ifdef WANT_CLOSED_TRACKER
465 "\n* To white list a torrent, touch a file inside serverdir with info_hash hex string.\n"
466#endif
467#ifdef WANT_BLACKLIST
468#ifndef WANT_CLOSED_TRACKER
469 "\n"
470#endif
471 "* To white list a torrent, touch a file inside serverdir with info_hash hex string, preprended by '-'.\n"
472#endif
473 "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -i 10.1.1.23 -p 2710 -p 80\n" 496 "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -i 10.1.1.23 -p 2710 -p 80\n"
474); 497);
475} 498}
@@ -503,7 +526,7 @@ static void handle_read( const int64 clientsocket ) {
503 if( array_failed( &h->request ) ) 526 if( array_failed( &h->request ) )
504 return httperror( clientsocket, "500 Server Error", "Request too long."); 527 return httperror( clientsocket, "500 Server Error", "Request too long.");
505 528
506 if( array_bytes( &h->request ) > 8192 ) 529 if( ( !h->blessed ) && ( array_bytes( &h->request ) > 8192 ) )
507 return httperror( clientsocket, "500 request too long", "You sent too much headers"); 530 return httperror( clientsocket, "500 request too long", "You sent too much headers");
508 531
509 if( memchr( array_start( &h->request ), '\n', array_length( &h->request, 1 ) ) ) 532 if( memchr( array_start( &h->request ), '\n', array_length( &h->request, 1 ) ) )
@@ -626,7 +649,7 @@ static void handle_udp4( int64 serversocket ) {
626 outpacket[3] = outpacket[4] = 0; 649 outpacket[3] = outpacket[4] = 0;
627 r = 20; 650 r = 20;
628 } else { 651 } else {
629 torrent = add_peer_to_torrent( hash, &peer ); 652 torrent = add_peer_to_torrent( hash, &peer, 0 );
630 if( !torrent ) 653 if( !torrent )
631 return; /* XXX maybe send error */ 654 return; /* XXX maybe send error */
632 655
@@ -719,14 +742,6 @@ int main( int argc, char **argv ) {
719 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); break; 742 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); break;
720 case 'd': serverdir = optarg; break; 743 case 'd': serverdir = optarg; break;
721 case 'h': help( argv[0] ); exit( 0 ); 744 case 'h': help( argv[0] ); exit( 0 );
722#ifdef WANT_CLOSED_TRACKER
723 case 'o': g_closedtracker = 0; break;
724 case 'c': g_closedtracker = 1; break;
725#endif
726#ifdef WANT_BLACKLIST
727 case 'b': g_check_blacklist = 1; break;
728 case 'B': g_check_blacklist = 0; break;
729#endif
730 default: 745 default:
731 case '?': usage( argv[0] ); exit( 1 ); 746 case '?': usage( argv[0] ); exit( 1 );
732 } 747 }
diff --git a/trackerlogic.c b/trackerlogic.c
index d2d279e..5bda0df 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -19,26 +19,12 @@
19#include "scan.h" 19#include "scan.h"
20#include "byte.h" 20#include "byte.h"
21 21
22#if defined( WANT_CLOSED_TRACKER ) || defined( WANT_BLACKLIST )
23#include <sys/stat.h>
24#endif
25
26/* GLOBAL VARIABLES */ 22/* GLOBAL VARIABLES */
27static ot_vector all_torrents[256]; 23static ot_vector all_torrents[256];
28static ot_vector changeset; 24static ot_vector changeset;
29size_t changeset_size = 0; 25size_t changeset_size = 0;
30time_t last_clean_time = 0; 26time_t last_clean_time = 0;
31 27
32#ifdef WANT_CLOSED_TRACKER
33int g_closedtracker = 1;
34static ot_torrent* const OT_TORRENT_NOT_ON_WHITELIST = (ot_torrent*)1;
35#endif
36
37#ifdef WANT_BLACKLIST
38int g_check_blacklist = 1;
39static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2;
40#endif
41
42/* Converter function from memory to human readable hex strings 28/* Converter function from memory to human readable hex strings
43 - definitely not thread safe!!! 29 - definitely not thread safe!!!
44*/ 30*/
@@ -162,25 +148,12 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) {
162 return 1; 148 return 1;
163} 149}
164 150
165ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { 151ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) {
166 int exactmatch; 152 int exactmatch;
167 ot_torrent *torrent; 153 ot_torrent *torrent;
168 ot_peer *peer_dest; 154 ot_peer *peer_dest;
169 ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool; 155 ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool;
170#if defined( WANT_CLOSED_TRACKER ) || defined( WANT_BLACKLIST ) 156 int base_pool = 0;
171 struct stat dummy_sb;
172 char *fn = to_hex( (ot_byte*)hash );
173#endif
174
175#ifdef WANT_CLOSED_TRACKER
176 if( g_closedtracker && stat( fn, &dummy_sb ) )
177 return OT_TORRENT_NOT_ON_WHITELIST;
178#endif
179
180#ifdef WANT_BLACKLIST
181 if( g_check_blacklist && !stat( fn - 1, &dummy_sb ) )
182 return OT_TORRENT_ON_BLACKLIST;
183#endif
184 157
185 torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); 158 torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
186 if( !torrent ) return NULL; 159 if( !torrent ) return NULL;
@@ -202,7 +175,16 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
202 if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) 175 if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED )
203 OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; 176 OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED;
204 177
205 peer_pool = &torrent->peer_list->peers[0]; 178 if( from_changeset ) {
179 /* Check, whether peer already is in current pool, do nothing if so */
180 peer_pool = &torrent->peer_list->peers[0];
181 binary_search( peer, peer_pool->data, peer_pool->size, sizeof(ot_peer), OT_PEER_COMPARE_SIZE, &exactmatch );
182 if( exactmatch )
183 return torrent;
184 base_pool = 1;
185 }
186
187 peer_pool = &torrent->peer_list->peers[ base_pool ];
206 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); 188 peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch );
207 189
208 /* If we hadn't had a match in current pool, create peer there and 190 /* If we hadn't had a match in current pool, create peer there and
@@ -215,9 +197,9 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
215 torrent->peer_list->downloaded++; 197 torrent->peer_list->downloaded++;
216 198
217 if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) 199 if( OT_FLAG(peer) & PEER_FLAG_SEEDING )
218 torrent->peer_list->seed_count[0]++; 200 torrent->peer_list->seed_count[ base_pool ]++;
219 201
220 for( i=1; i<OT_POOLS_COUNT; ++i ) { 202 for( i= base_pool + 1; i<OT_POOLS_COUNT; ++i ) {
221 switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) { 203 switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) {
222 case 0: continue; 204 case 0: continue;
223 case 2: torrent->peer_list->seed_count[i]--; 205 case 2: torrent->peer_list->seed_count[i]--;
@@ -226,9 +208,9 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
226 } 208 }
227 } else { 209 } else {
228 if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) 210 if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) )
229 torrent->peer_list->seed_count[0]--; 211 torrent->peer_list->seed_count[ base_pool ]--;
230 if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) 212 if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) )
231 torrent->peer_list->seed_count[0]++; 213 torrent->peer_list->seed_count[ base_pool ]++;
232 if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) ) 214 if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) )
233 torrent->peer_list->downloaded++; 215 torrent->peer_list->downloaded++;
234 if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) 216 if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED )
@@ -250,22 +232,6 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply
250 char *r = reply; 232 char *r = reply;
251 size_t peer_count, seed_count, index; 233 size_t peer_count, seed_count, index;
252 234
253#ifdef WANT_CLOSED_TRACKER
254 if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) {
255 const char * const notvalid = "d14:failure reason43:This torrent is not served by this tracker.e";
256 memmove( reply, notvalid, sizeof(notvalid));
257 return sizeof(notvalid);
258 }
259#endif
260
261#ifdef WANT_BLACKLIST
262 if( torrent == OT_TORRENT_ON_BLACKLIST ) {
263 const char * const blacklisted = "d14:failure reason29:This torrent is black listed.e";
264 memmove( reply, blacklisted, sizeof(blacklisted));
265 return sizeof(blacklisted);
266 }
267#endif
268
269 for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) { 235 for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) {
270 peer_count += torrent->peer_list->peers[index].size; 236 peer_count += torrent->peer_list->peers[index].size;
271 seed_count += torrent->peer_list->seed_count[index]; 237 seed_count += torrent->peer_list->seed_count[index];
@@ -473,8 +439,48 @@ static void add_pool_to_changeset( ot_hash *hash, ot_peer *peers, size_t peer_co
473 changeset_size += r - sizeof( size_t ); 439 changeset_size += r - sizeof( size_t );
474} 440}
475 441
442/* Import Changeset from an external authority
443 format: d4:syncd[..]ee
444 [..]: ( 20:01234567890abcdefghij16:XXXXYYYY )+
445*/
446int add_changeset_to_tracker( ot_byte *data, size_t len ) {
447 ot_hash *hash;
448 ot_byte *end = data + len;
449 size_t peer_count;
450
451 /* We do know, that the string is \n terminated, so it cant
452 overflow */
453 if( byte_diff( data, 8, "d4:syncd" ) ) return -1;
454 data += 8;
455
456 while( 1 ) {
457 if( byte_diff( data, 3, "20:" ) ) {
458 if( byte_diff( data, 2, "ee" ) )
459 return -1;
460 return 0;
461 }
462 data += 3;
463 hash = (ot_hash*)data;
464 data += sizeof( ot_hash );
465
466 /* Scan string length indicator */
467 data += ( len = scan_ulong( (char*)data, &peer_count ) );
468
469 /* If no long was scanned, it is not divisible by 8, it is not
470 followed by a colon or claims to need to much memory, we fail */
471 if( !len || !peer_count || ( peer_count & 7 ) || ( *data++ != ':' ) || ( data + peer_count > end ) )
472 return -1;
473
474 while( peer_count > 0 ) {
475 add_peer_to_torrent( hash, (ot_peer*)data, 1 );
476 data += 8; peer_count -= 8;
477 }
478 }
479 return 0;
480}
481
476/* Proposed output format 482/* Proposed output format
477 d4:syncd20:<info_hash>8*N:(xxxxyy)*Nee 483 d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee
478*/ 484*/
479size_t return_changeset_for_tracker( char **reply ) { 485size_t return_changeset_for_tracker( char **reply ) {
480 size_t i, r = 8; 486 size_t i, r = 8;
diff --git a/trackerlogic.h b/trackerlogic.h
index dfd5047..4fa48eb 100644
--- a/trackerlogic.h
+++ b/trackerlogic.h
@@ -84,16 +84,10 @@ typedef struct {
84int init_logic( const char * const serverdir ); 84int init_logic( const char * const serverdir );
85void deinit_logic( void ); 85void deinit_logic( void );
86 86
87#ifdef WANT_CLOSED_TRACKER 87enum { STATS_MRTG, STATS_TOP5, STATS_DMEM, STATS_TCP, STATS_UDP, SYNC_IN, SYNC_OUT };
88extern int g_closedtracker;
89#endif
90#ifdef WANT_BLACKLIST
91extern int g_check_blacklist;
92#endif
93
94enum { STATS_MRTG, STATS_TOP5, STATS_DMEM, STATS_TCP, STATS_UDP };
95 88
96ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ); 89ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset );
90int add_changeset_to_tracker( ot_byte *data, size_t len );
97size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ); 91size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp );
98size_t return_fullscrape_for_tracker( char **reply ); 92size_t return_fullscrape_for_tracker( char **reply );
99size_t return_tcp_scrape_for_torrent( ot_hash *hash, char *reply ); 93size_t return_tcp_scrape_for_torrent( ot_hash *hash, char *reply );