Introduce another unspec'd command: sync which syncs the most recent peer pool for a torrent out. Do some variable type clean up. Do some code structure clean up.

dynamic-accesslists
erdgeist 18 years ago
parent dffea5da69
commit 05420c40e5

@ -26,6 +26,7 @@
#include "trackerlogic.h"
#include "scan_urlencoded_query.h"
/* Globals */
static unsigned int ot_overall_connections = 0;
static unsigned int ot_overall_successfulannounces = 0;
static time_t ot_start_time;
@ -34,35 +35,64 @@ static const size_t SUCCESS_HTTP_SIZE_OFF = 17;
/* To always have space for error messages ;) */
static char static_scratch[8192];
#ifdef _DEBUG_FDS
static char fd_debug_space[0x10000];
#endif
#ifdef _DEBUG_HTTPERROR
static char debug_request[8192];
#endif
static void carp(const char* routine ) {
struct http_data {
union {
array request;
io_batch batch;
};
unsigned char ip[4];
};
/* Prototypes */
int main( int argc, char **argv );
static int httpheader_complete( struct http_data *h );
static void httperror( const int64 s, struct http_data *h, const char *title, const char *message );
static void httpresponse( const int64 s, struct http_data *h);
static void sendmallocdata( const int64 s, struct http_data *h, char *buffer, const size_t size );
static void senddata( const int64 s, struct http_data *h, char *buffer, const size_t size );
static void server_mainloop( const int64 serversocket );
static void handle_timeouted( void );
static void handle_accept( const int64 serversocket );
static void handle_read( const int64 clientsocket );
static void handle_write( const int64 clientsocket );
static void usage( char *name );
static void help( char *name );
static void carp( const char *routine );
static void panic( const char *routine );
static void graceful( int s );
#define HTTPERROR_400 return httperror( s, h, "400 Invalid Request", "This server only understands GET." )
#define HTTPERROR_400_PARAM return httperror( s, h, "400 Invalid Request", "Invalid parameter" )
#define HTTPERROR_400_COMPACT return httperror( s, h, "400 Invalid Request", "This server only delivers compact results." )
#define HTTPERROR_404 return httperror( s, h, "404 Not Found", "No such file or directory." )
#define HTTPERROR_500 return httperror( s, h, "500 Internal Server Error", "A server error has occured. Please retry later." )
/* End of prototypes */
static void carp( const char *routine ) {
buffer_puts( buffer_2, routine );
buffer_puts( buffer_2, ": " );
buffer_puterror( buffer_2 );
buffer_putnlflush( buffer_2 );
}
static void panic( const char* routine ) {
static void panic( const char *routine ) {
carp( routine );
exit( 111 );
}
struct http_data {
union {
array request;
io_batch batch;
};
unsigned char ip[4];
};
int header_complete( struct http_data* h ) {
int l = array_bytes( &h->request ), i;
static int httpheader_complete( struct http_data *h ) {
size_t l = array_bytes( &h->request ), i;
const char* c = array_start( &h->request );
for( i=0; i+1<l; ++i) {
@ -72,16 +102,29 @@ int header_complete( struct http_data* h ) {
return 0;
}
void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size ) {
static void httperror( const int64 s, struct http_data *h, const char *title, const char *message ) {
size_t reply_size = sprintf( static_scratch, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n",
title, strlen(message)+strlen(title)+16-4,title+4);
#ifdef _DEBUG_HTTPERROR
fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request );
#endif
senddata(s,h,static_scratch,reply_size);
}
static void sendmallocdata( const int64 s, struct http_data *h, char *buffer, size_t size ) {
tai6464 t;
char *header;
size_t header_size;
if( !h ) { free( buffer); return; }
if( !h )
return free( buffer);
array_reset( &h->request );
header = malloc( SUCCESS_HTTP_HEADER_LENGTH );
if( !header ) { free( buffer ); return; }
if( !header ) {
free( buffer );
HTTPERROR_500;
}
header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size );
@ -89,13 +132,13 @@ void sendmallocdata( int64 s, struct http_data *h, char * buffer, size_t size )
iob_addbuf_free( &h->batch, header, header_size );
iob_addbuf_free( &h->batch, buffer, size );
// writeable sockets just have a tcp timeout
/* writeable sockets just have a tcp timeout */
taia_uint(&t,0); io_timeout( s, t );
io_dontwantread( s );
io_wantwrite( s );
}
void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
static void senddata( const int64 s, struct http_data *h, char *buffer, size_t size ) {
size_t written_size;
/* whoever sends data is not interested in its input-array */
@ -104,20 +147,12 @@ void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
written_size = write( s, buffer, size );
if( ( written_size < 0 ) || ( written_size == size ) ) {
#ifdef _DEBUG_FDS
if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[s] = 0;
#endif
free( h ); io_close( s );
} else {
char * outbuf = malloc( size - written_size );
tai6464 t;
if( !outbuf ) {
#ifdef _DEBUG_FDS
if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[s] = 0;
#endif
free(h); io_close( s );
return;
}
@ -126,29 +161,21 @@ void senddata(int64 s, struct http_data* h, char *buffer, size_t size ) {
memmove( outbuf, buffer + written_size, size - written_size );
iob_addbuf_free( &h->batch, outbuf, size - written_size );
// writeable sockets just have a tcp timeout
/* writeable sockets just have a tcp timeout */
taia_uint( &t, 0 ); io_timeout( s, t );
io_dontwantread( s );
io_wantwrite( s );
}
}
void httperror(int64 s,struct http_data* h,const char* title,const char* message) {
size_t reply_size = sprintf( static_scratch, "HTTP/1.0 %s\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: %zd\r\n\r\n<title>%s</title>\n",
title, strlen(message)+strlen(title)+16-4,title+4);
#ifdef _DEBUG_HTTPERROR
fprintf( stderr, "DEBUG: invalid request was: %s\n", debug_request );
#endif
senddata(s,h,static_scratch,reply_size);
}
void httpresponse( int64 s, struct http_data* h) {
char *c, *data;
static void httpresponse( const int64 s, struct http_data *h) {
char *c, *data, *reply;
ot_peer peer;
ot_torrent *torrent;
ot_hash *hash = NULL;
int numwant, tmp, scanon, mode;
unsigned short port = htons(6881);
time_t t;
size_t reply_size = 0;
array_cat0( &h->request );
@ -158,104 +185,106 @@ void httpresponse( int64 s, struct http_data* h) {
memcpy( debug_request, array_start( &h->request ), array_bytes( &h->request ) );
#endif
if( byte_diff( c, 4, "GET ") ) {
e400:
return httperror( s, h, "400 Invalid Request", "This server only understands GET." );
}
if( byte_diff( c, 4, "GET ") ) HTTPERROR_400;
c+=4;
for( data = c; *data!=' ' && *data != '\t' && *data != '\n' && *data != '\r'; ++data ) ;
if( *data != ' ' ) goto e400;
if( *data != ' ' ) HTTPERROR_400;
*data = 0;
if( c[0] != '/' ) goto e404;
if( c[0] != '/' ) HTTPERROR_404;
while( *c == '/' ) ++c;
switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
case 4: /* sync ? */
if( byte_diff( data, 4, "sync") ) HTTPERROR_404;
scanon = 1;
while( scanon ) {
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
case 9:
if(byte_diff(data,9,"info_hash")) {
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
continue;
}
/* ignore this, when we have less than 20 bytes */
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
hash = (ot_hash*)data; /* Fall through intended */
break;
default:
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
break;
}
}
if( !hash ) HTTPERROR_400_PARAM;
if( ( reply_size = return_sync_for_torrent( hash, &reply ) ) <= 0 ) HTTPERROR_500;
return sendmallocdata( s, h, reply, reply_size );
case 5: /* stats ? */
if( byte_diff(data,5,"stats"))
goto e404;
if( byte_diff(data,5,"stats")) HTTPERROR_404;
scanon = 1;
mode = STATS_MRTG;
while( scanon ) {
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
case -2: /* terminator */
scanon = 0;
break;
case -1: /* error */
goto e404;
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
default: scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); break;
case 4:
if( byte_diff(data,4,"mode")) {
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
continue;
}
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
if( len <= 0 ) goto e400_param;
if( len <= 0 ) HTTPERROR_400_PARAM;
if( !byte_diff(data,4,"mrtg"))
mode = STATS_MRTG;
else if( !byte_diff(data,4,"top5"))
mode = STATS_TOP5;
else
goto e400_param;
default:
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
break;
HTTPERROR_400_PARAM;
}
}
/* Enough for http header + whole scrape string */
if( ( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_scratch, mode ) ) <= 0 )
goto e500;
if( ( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_scratch, mode ) ) <= 0 ) HTTPERROR_500;
break;
case 6: /* scrape ? */
if( byte_diff( data, 6, "scrape") )
goto e404;
if( byte_diff( data, 6, "scrape") ) HTTPERROR_404;
scanon = 1;
while( scanon ) {
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
case -2: /* terminator */
scanon = 0;
break;
case -1: /* error */
goto e404;
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
default: scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); break;
case 9:
if(byte_diff(data,9,"info_hash")) {
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
continue;
}
/* ignore this, when we have less than 20 bytes */
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) {
e400_param:
return httperror(s,h,"400 Invalid Request","Invalid parameter");
}
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
hash = (ot_hash*)data; /* Fall through intended */
break;
default:
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
break;
}
}
/* Scanned whole query string, no hash means full scrape... you might want to limit that */
if( !hash ) {
char * reply;
reply_size = return_fullscrape_for_tracker( &reply );
if( reply_size )
if( ( reply_size = return_fullscrape_for_tracker( &reply ) ) <= 0 ) HTTPERROR_500;
return sendmallocdata( s, h, reply, reply_size );
}
goto e500;
} else {
/* Enough for http header + whole scrape string */
if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_scratch ) ) <= 0 )
goto e500;
}
if( ( reply_size = return_scrape_for_torrent( hash, SUCCESS_HTTP_HEADER_LENGTH + static_scratch ) ) <= 0 ) HTTPERROR_500;
break;
case 8:
if( byte_diff(data,8,"announce"))
goto e404;
if( byte_diff(data,8,"announce")) HTTPERROR_404;
OT_SETIP( &peer, h->ip);
OT_SETPORT( &peer, &port );
@ -265,17 +294,15 @@ e400_param:
while( scanon ) {
switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
case -2: /* terminator */
scanon = 0;
break;
case -1: /* error */
goto e404;
case -2: scanon = 0; break; /* TERMINATOR */
case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
default: scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); break;
#ifdef WANT_IP_FROM_QUERY_STRING
case 2:
if(!byte_diff(data,2,"ip")) {
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
unsigned char ip[4];
if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) goto e400_param;
if( ( len <= 0 ) || scan_fixed_ip( data, len, ip ) ) HTTPERROR_400_PARAM;
OT_SETIP( &peer, ip );
} else
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
@ -284,11 +311,11 @@ e400_param:
case 4:
if(!byte_diff(data,4,"port")) {
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) goto e400_param;
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) || ( tmp > 0xffff ) ) HTTPERROR_400_PARAM;
port = htons( tmp ); OT_SETPORT( &peer, &port );
} else if(!byte_diff(data,4,"left")) {
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
if( len <= 0 ) goto e400_param;
if( len <= 0 ) HTTPERROR_400_PARAM;
if( scan_fixed_int( data, len, &tmp ) ) tmp = 0;
if( !tmp ) OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
} else
@ -299,7 +326,7 @@ e400_param:
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
else switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) {
case -1:
goto e400_param;
HTTPERROR_400_PARAM;
case 7:
if(!byte_diff(data,7,"stopped")) OT_FLAG( &peer ) |= PEER_FLAG_STOPPED;
break;
@ -312,13 +339,12 @@ e400_param:
case 7:
if(!byte_diff(data,7,"numwant")) {
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) goto e400_param;
if( ( len <= 0 ) || scan_fixed_int( data, len, &numwant ) ) HTTPERROR_400_PARAM;
if( numwant > 200 ) numwant = 200;
} else if(!byte_diff(data,7,"compact")) {
size_t len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE );
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) goto e400_param;
if( !tmp )
return httperror(s,h,"400 Invalid Request","This server only delivers compact results.");
if( ( len <= 0 ) || scan_fixed_int( data, len, &tmp ) ) HTTPERROR_400_PARAM;
if( !tmp ) HTTPERROR_400_COMPACT;
} else
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
break;
@ -328,50 +354,38 @@ e400_param:
continue;
}
/* ignore this, when we have less than 20 bytes */
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 )
goto e400;
if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
hash = (ot_hash*)data;
break;
default:
scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
break;
}
}
/* Scanned whole query string */
if( !hash ) goto e400;
if( !hash ) HTTPERROR_400_PARAM;
if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
remove_peer_from_torrent( hash, &peer );
reply_size = sprintf( static_scratch + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM );
} else {
torrent = add_peer_to_torrent( hash, &peer );
if( !torrent ) {
e500:
return httperror(s,h,"500 Internal Server Error","A server error has occured. Please retry later.");
}
if( ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_scratch ) ) <= 0 )
goto e500;
if( !torrent || ( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_scratch ) ) <= 0 ) HTTPERROR_500;
}
ot_overall_successfulannounces++;
break;
case 11:
if( byte_diff(data,11,"mrtg_scrape"))
goto e404;
{
time_t seconds_elapsed = time( NULL ) - ot_start_time;
if( byte_diff(data,11,"mrtg_scrape")) HTTPERROR_404;
t = time( NULL ) - ot_start_time;
reply_size = sprintf( static_scratch + SUCCESS_HTTP_HEADER_LENGTH,
"%i\n%i\nUp: %i seconds (%i hours)\nPretuned by german engineers, currently handling %i connections per second.",
ot_overall_connections, ot_overall_successfulannounces, (int)seconds_elapsed,
(int)(seconds_elapsed / 3600), (int)ot_overall_connections / ( (int)seconds_elapsed ? (int)seconds_elapsed : 1 ) );
}
ot_overall_connections, ot_overall_successfulannounces, (int)t, (int)(t / 3600), (int)ot_overall_connections / ( (int)t ? (int)t : 1 ) );
break;
default: /* neither *scrape nor announce */
e404:
return httperror( s, h, "404 Not Found", "No such file or directory." );
HTTPERROR_404;
}
if( reply_size ) {
if( reply_size <= 0 ) HTTPERROR_500;
/* This one is rather ugly, so I take you step by step through it.
1. In order to avoid having two buffers, one for header and one for content, we allow all above functions from trackerlogic to
@ -389,18 +403,9 @@ e404:
static_scratch[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
senddata( s, h, static_scratch + reply_off, reply_size );
} else {
if( h )
array_reset( &h->request );
#ifdef _DEBUG_FDS
if( !fd_debug_space[s] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[s] = 0;
#endif
free( h ); io_close( s );
}
}
void graceful( int s ) {
static void graceful( int s ) {
if( s == SIGINT ) {
signal( SIGINT, SIG_IGN);
deinit_logic();
@ -408,16 +413,7 @@ void graceful( int s ) {
}
}
#ifdef _DEBUG_FDS
void count_fds( int s ) {
int i, count = 0;
for( i=0; i<sizeof(fd_debug_space); ++i )
if( fd_debug_space[i] ) ++count;
fprintf( stderr, "Open fds here: %i\n", count );
}
#endif
void usage( char *name ) {
static void usage( char *name ) {
fprintf( stderr, "Usage: %s [-i serverip] [-p serverport] [-d serverdirectory]"
#ifdef WANT_CLOSED_TRACKER
" [-oc]"
@ -428,7 +424,7 @@ void usage( char *name ) {
"\n", name );
}
void help( char *name ) {
static void help( char *name ) {
usage( name );
fprintf( stderr, "\t-i serverip\tspecify ip to bind to (default: *)\n"
"\t-p serverport\tspecify port to bind to (default: 6969)\n"
@ -453,19 +449,15 @@ void help( char *name ) {
);
}
void handle_read( int64 clientsocket ) {
static void handle_read( const int64 clientsocket ) {
struct http_data* h = io_getcookie( clientsocket );
int l = io_tryread( clientsocket, static_scratch, sizeof static_scratch );
size_t l;
if( l <= 0 ) {
if( ( l = io_tryread( clientsocket, static_scratch, sizeof static_scratch ) ) <= 0 ) {
if( h ) {
array_reset( &h->request );
free( h );
}
#ifdef _DEBUG_FDS
if( !fd_debug_space[clientsocket] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[clientsocket] = 0;
#endif
io_close( clientsocket );
return;
}
@ -480,26 +472,22 @@ void handle_read( int64 clientsocket ) {
httperror( clientsocket, h, "500 Server Error", "Request too long.");
else if( array_bytes( &h->request ) > 8192 )
httperror( clientsocket, h, "500 request too long", "You sent too much headers");
else if( ( l = header_complete( h ) ) )
else if( ( l = httpheader_complete( h ) ) )
httpresponse( clientsocket, h);
}
void handle_write( int64 clientsocket ) {
static void handle_write( const int64 clientsocket ) {
struct http_data* h=io_getcookie( clientsocket );
if( !h ) return;
if( iob_send( clientsocket, &h->batch ) <= 0 ) {
iob_reset( &h->batch );
#ifdef _DEBUG_FDS
if( !fd_debug_space[clientsocket] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[clientsocket] = 0;
#endif
io_close( clientsocket );
free( h );
}
}
void handle_accept( int64 serversocket ) {
struct http_data* h;
static void handle_accept( const int64 serversocket ) {
struct http_data *h;
unsigned char ip[4];
uint16 port;
tai6464 t;
@ -513,11 +501,6 @@ void handle_accept( int64 serversocket ) {
continue;
}
#ifdef _DEBUG_FDS
if( fd_debug_space[i] ) fprintf( stderr, "double use of fd: %i\n", (int)i );
fd_debug_space[i] = 1;
#endif
io_wantread( i );
byte_zero(h,sizeof(struct http_data));
@ -531,13 +514,9 @@ void handle_accept( int64 serversocket ) {
if( errno==EAGAIN )
io_eagain( serversocket );
/*
else
carp( "socket_accept4" );
*/
}
void handle_timeouted( ) {
static void handle_timeouted( void ) {
int64 i;
while( ( i = io_timeouted() ) != -1 ) {
struct http_data* h=io_getcookie( i );
@ -545,15 +524,11 @@ void handle_timeouted( ) {
array_reset( &h->request );
free( h );
}
#ifdef _DEBUG_FDS
if( !fd_debug_space[i] ) fprintf( stderr, "close on non-open fd\n" );
fd_debug_space[i] = 0;
#endif
io_close(i);
}
}
void server_mainloop( int64 serversocket ) {
static void server_mainloop( const int64 serversocket ) {
tai6464 t, next_timeout_check;
io_wantread( serversocket );
@ -626,9 +601,6 @@ int main( int argc, char **argv ) {
signal( SIGPIPE, SIG_IGN );
signal( SIGINT, graceful );
#ifdef _DEBUG_FDS
signal( SIGINFO, count_fds );
#endif
if( init_logic( serverdir ) == -1 )
panic( "Logic not started" );

@ -64,7 +64,7 @@ static void *binary_search( const void * const key, const void * base, const siz
*/
char 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;}
static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, int compare_size, int *exactmatch ) {
static void *vector_find_or_insert( ot_vector *vector, void *key, size_t member_size, size_t compare_size, int *exactmatch ) {
ot_byte *match = binary_search( key, vector->data, vector->size, member_size, compare_size, exactmatch );
if( *exactmatch ) return match;
@ -104,7 +104,7 @@ static int vector_remove_peer( ot_vector *vector, ot_peer *peer ) {
}
static void free_peerlist( ot_peerlist *peer_list ) {
int i;
size_t i;
for( i=0; i<OT_POOLS_COUNT; ++i )
if( peer_list->peers[i].data )
free( peer_list->peers[i].data );
@ -227,9 +227,9 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) {
* RANDOM may return huge values
* does not yet check not to return self
*/
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) {
size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply ) {
char *r = reply;
unsigned int peer_count, seed_count, index;
size_t peer_count, seed_count, index;
#ifdef WANT_CLOSED_TRACKER
if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) {
@ -247,13 +247,13 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char
}
#endif
for( peer_count=seed_count=index=0; index<OT_POOLS_COUNT; ++index) {
for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) {
peer_count += torrent->peer_list->peers[index].size;
seed_count += torrent->peer_list->seed_count[index];
}
if( peer_count < amount ) amount = peer_count;
r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali%ie5:peers%i:", seed_count, peer_count-seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount );
r += sprintf( r, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers%zd:", seed_count, peer_count-seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount );
if( amount ) {
unsigned int pool_offset, pool_index = 0;;
unsigned int shifted_pc = peer_count;
@ -292,8 +292,9 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char
/* Fetch full scrape info for all torrents */
size_t return_fullscrape_for_tracker( char **reply ) {
int torrent_count = 0, i, j, k;
char* r;
size_t torrent_count = 0, j;
int i, k;
char *r;
time_t time_now = NOW;
for( i=0; i<256; ++i ) {
@ -301,8 +302,7 @@ size_t return_fullscrape_for_tracker( char **reply ) {
torrent_count += torrents_list->size;
}
r = *reply = malloc( 128*torrent_count );
if( !reply ) return 0;
if( !( r = *reply = malloc( 128*torrent_count ) ) ) return 0;
memmove( r, "d5:filesd", 9 ); r += 9;
for( i=0; i<256; ++i ) {
@ -310,7 +310,7 @@ size_t return_fullscrape_for_tracker( char **reply ) {
for( j=0; j<torrents_list->size; ++j ) {
ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[j] ).hash;
int peers = 0, seeds = 0;
size_t peers = 0, seeds = 0;
clean_peerlist( time_now, peer_list );
for( k=0; k<OT_POOLS_COUNT; ++k ) {
peers += peer_list->peers[k].size;
@ -318,7 +318,7 @@ size_t return_fullscrape_for_tracker( char **reply ) {
}
memmove( r, "20:", 3 ); r+=3;
memmove( r, hash, 20 ); r+=20;
r += sprintf( r, "d8:completei%de10:downloadedi%de10:incompletei%de", seeds, peer_list->downloaded, peers-seeds );
r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde", seeds, peer_list->downloaded, peers-seeds );
}
}
@ -329,7 +329,8 @@ size_t return_fullscrape_for_tracker( char **reply ) {
/* Fetches scrape info for a specific torrent */
size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
char *r = reply;
int exactmatch, peers = 0, seeds = 0, i;
int exactmatch, i;
size_t peers = 0, seeds = 0;
ot_vector *torrents_list = &all_torrents[*hash[0]];
ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
@ -342,20 +343,45 @@ size_t return_scrape_for_torrent( ot_hash *hash, char *reply ) {
}
memmove( r, "d5:filesd20:", 12 ); memmove( r+12, hash, 20 );
r += sprintf( r+32, "d8:completei%de10:downloadedi%de10:incompletei%deeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
r += sprintf( r+32, "d8:completei%zde10:downloadedi%zde10:incompletei%zdeeee", seeds, torrent->peer_list->downloaded, peers-seeds ) + 32;
return r - reply;
}
size_t return_sync_for_torrent( ot_hash *hash, char **reply ) {
int exactmatch;
size_t peers = 0;
char *r;
ot_vector *torrents_list = &all_torrents[*hash[0]];
ot_torrent *torrent = binary_search( hash, torrents_list->data, torrents_list->size, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
if( exactmatch ) {
clean_peerlist( NOW, torrent->peer_list );
peers = torrent->peer_list->peers[0].size;
}
if( !( r = *reply = malloc( 10 + peers * sizeof( ot_peer ) ) ) ) return 0;
memmove( r, "d4:sync", 7 );
r += 7;
r += sprintf( r, "%zd:", peers * sizeof( ot_peer ) );
if( peers ) {
memmove( r, torrent->peer_list->peers[0].data, peers * sizeof( ot_peer ) );
r += peers * sizeof( ot_peer );
}
*r++ = 'e';
return r - *reply;
}
typedef struct { int val; ot_torrent * torrent; } ot_record;
/* Fetches stats from tracker */
size_t return_stats_for_tracker( char *reply, int mode ) {
time_t time_now = NOW;
int torrent_count = 0, peer_count = 0, seed_count = 0;
size_t torrent_count = 0, peer_count = 0, seed_count = 0, j;
ot_record top5s[5], top5c[5];
char *r = reply;
int i,j,k;
int i,k;
byte_zero( top5s, sizeof( top5s ) );
byte_zero( top5c, sizeof( top5c ) );
@ -365,7 +391,7 @@ size_t return_stats_for_tracker( char *reply, int mode ) {
torrent_count += torrents_list->size;
for( j=0; j<torrents_list->size; ++j ) {
ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list;
int local_peers = 0, local_seeds = 0;
size_t local_peers = 0, local_seeds = 0;
clean_peerlist( time_now, peer_list );
for( k=0; k<OT_POOLS_COUNT; ++k ) {
local_peers += peer_list->peers[k].size;
@ -399,7 +425,7 @@ size_t return_stats_for_tracker( char *reply, int mode ) {
if( top5s[idx].torrent )
r += sprintf( r, "\t%i\t%s\n", top5s[idx].val, to_hex(top5s[idx].torrent->hash) );
} else {
r += sprintf( r, "%i\n%i\nopentracker serving %i torrents\nSomething else.", peer_count, seed_count, torrent_count );
r += sprintf( r, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", peer_count, seed_count, torrent_count );
}
return r - reply;
@ -429,7 +455,7 @@ void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ) {
}
}
int init_logic( char *serverdir ) {
int init_logic( const char * const serverdir ) {
if( serverdir && chdir( serverdir ) ) {
fprintf( stderr, "Could not chdir() to %s\n", serverdir );
return -1;
@ -443,8 +469,9 @@ int init_logic( char *serverdir ) {
return 0;
}
void deinit_logic( ) {
int i, j;
void deinit_logic( void ) {
int i;
size_t j;
/* Free all torrents... */
for(i=0; i<256; ++i ) {

@ -64,7 +64,7 @@ static const ot_byte PEER_FLAG_STOPPED = 0x20;
typedef struct {
ot_time base;
size_t seed_count[ OT_POOLS_COUNT ];
unsigned int downloaded;
size_t downloaded;
ot_vector peers[ OT_POOLS_COUNT ];
} ot_peerlist;
@ -77,8 +77,8 @@ typedef struct {
Exported functions
*/
int init_logic( char *serverdir );
void deinit_logic( );
int init_logic( const char * const serverdir );
void deinit_logic( void );
#ifdef WANT_CLOSED_TRACKER
extern int g_closedtracker;
@ -90,9 +90,10 @@ extern int g_check_blacklist;
enum { STATS_MRTG, STATS_TOP5 };
ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer );
size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply );
size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply );
size_t return_fullscrape_for_tracker( char **reply );
size_t return_scrape_for_torrent( ot_hash *hash, char *reply );
size_t return_sync_for_torrent( ot_hash *hash, char **reply );
size_t return_stats_for_tracker( char *reply, int mode );
void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer );

Loading…
Cancel
Save