mirror of
git://erdgeist.org/opentracker
synced 2025-01-14 00:40:09 +00:00
Fix white spaces
Introduce loading tracker states with -l Alter tracker state to a human readable form
This commit is contained in:
parent
a58bce83ad
commit
c7ed890222
@ -51,7 +51,7 @@ static void signal_handler( int s ) {
|
||||
if( s == SIGINT ) {
|
||||
/* Any new interrupt signal quits the application */
|
||||
signal( SIGINT, SIG_DFL);
|
||||
|
||||
|
||||
/* Tell all other threads to not acquire any new lock on a bucket
|
||||
but cancel their operations and return */
|
||||
g_opentracker_running = 0;
|
||||
@ -250,7 +250,7 @@ static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
|
||||
#else
|
||||
if( ip6_isv4mapped(ip) ) {
|
||||
exerr( "V6 Tracker is V6 only!" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
@ -261,7 +261,7 @@ static int64_t ot_try_bind( ot_ip6 ip, uint16_t port, PROTO_FLAG proto ) {
|
||||
snprintf( _debug + off, sizeof(_debug)-off, "]:%d...", port);
|
||||
fputs( _debug, stderr );
|
||||
#endif
|
||||
|
||||
|
||||
if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 )
|
||||
panic( "socket_bind6_reuse" );
|
||||
|
||||
@ -394,6 +394,42 @@ int parse_configfile( char * config_filename ) {
|
||||
return bound;
|
||||
}
|
||||
|
||||
void load_state(const char * const state_filename ) {
|
||||
FILE * state_filehandle;
|
||||
char inbuf[512];
|
||||
ot_hash infohash;
|
||||
unsigned long long base, downcount;
|
||||
int consumed;
|
||||
|
||||
state_filehandle = fopen( state_filename, "r" );
|
||||
|
||||
if( state_filehandle == NULL ) {
|
||||
fprintf( stderr, "Warning: Can't open config file: %s.", state_filename );
|
||||
return;
|
||||
}
|
||||
|
||||
/* We do ignore anything that is not of the form "^[:xdigit:]:\d+:\d+" */
|
||||
while( fgets( inbuf, sizeof(inbuf), state_filehandle ) ) {
|
||||
int i;
|
||||
for( i=0; i<(int)sizeof(ot_hash); ++i ) {
|
||||
int eger = 16 * scan_fromhex( inbuf[ 2*i ] ) + scan_fromhex( inbuf[ 1 + 2*i ] );
|
||||
if( eger < 0 )
|
||||
continue;
|
||||
infohash[i] = eger;
|
||||
}
|
||||
|
||||
if( i != (int)sizeof(ot_hash) ) continue;
|
||||
i *= 2;
|
||||
|
||||
if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &base ) ) ) continue;
|
||||
i += consumed;
|
||||
if( inbuf[ i++ ] != ':' || !( consumed = scan_ulonglong( inbuf+i, &downcount ) ) ) continue;
|
||||
add_torrent_from_saved_state( infohash, base, downcount );
|
||||
}
|
||||
|
||||
fclose( state_filehandle );
|
||||
}
|
||||
|
||||
int drop_privileges (const char * const serverdir) {
|
||||
struct passwd *pws = NULL;
|
||||
|
||||
@ -448,7 +484,7 @@ int main( int argc, char **argv ) {
|
||||
#endif
|
||||
|
||||
while( scanon ) {
|
||||
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:v"
|
||||
switch( getopt( argc, argv, ":i:p:A:P:d:r:s:f:l:v"
|
||||
#ifdef WANT_ACCESSLIST_BLACK
|
||||
"b:"
|
||||
#elif defined( WANT_ACCESSLIST_WHITE )
|
||||
@ -477,6 +513,7 @@ while( scanon ) {
|
||||
#endif
|
||||
case 'd': set_config_option( &g_serverdir, optarg ); break;
|
||||
case 'r': set_config_option( &g_redirecturl, optarg ); break;
|
||||
case 'l': load_state( optarg ); break;
|
||||
case 'A':
|
||||
if( !scan_ip6( optarg, tmpip )) { usage( argv[0] ); exit( 1 ); }
|
||||
accesslist_blessip( tmpip, 0xffff ); /* Allow everything for now */
|
||||
|
@ -120,7 +120,7 @@ int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ) {
|
||||
char _debug[512];
|
||||
int off = snprintf( _debug, sizeof(_debug), "Blessing ip address " );
|
||||
off += fmt_ip6(_debug+off, ip );
|
||||
|
||||
|
||||
if( permissions & OT_PERMISSION_MAY_STAT ) off += snprintf( _debug+off, 512-off, " may_fetch_stats" );
|
||||
if( permissions & OT_PERMISSION_MAY_LIVESYNC ) off += snprintf( _debug+off, 512-off, " may_sync_live" );
|
||||
if( permissions & OT_PERMISSION_MAY_FULLSCRAPE ) off += snprintf( _debug+off, 512-off, " may_fetch_fullscrapes" );
|
||||
|
@ -184,10 +184,8 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
|
||||
r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count );
|
||||
break;
|
||||
case TASK_FULLSCRAPE_TRACKERSTATE:
|
||||
memcpy( r, *hash, sizeof(ot_hash) ); r += sizeof(ot_hash);
|
||||
uint64_pack_big( r, (uint64_t)peer_list->down_count );
|
||||
uint64_pack_big( r + 8, (uint64_t)peer_list->base );
|
||||
r += 16;
|
||||
to_hex( r, *hash ); r+= 2 * sizeof(ot_hash);
|
||||
r += sprintf( r, ":%zd:%zd\n", peer_list->base, peer_list->down_count );
|
||||
break;
|
||||
}
|
||||
|
||||
|
11
ot_http.c
11
ot_http.c
@ -288,7 +288,7 @@ static ssize_t http_handle_scrape( const int64 sock, struct ot_workstruct *ws, c
|
||||
|
||||
/* No info_hash found? Inform user */
|
||||
if( !numwant ) HTTPERROR_400_PARAM;
|
||||
|
||||
|
||||
/* Limit number of hashes to process */
|
||||
if( numwant > OT_MAXMULTISCRAPE_COUNT )
|
||||
numwant = OT_MAXMULTISCRAPE_COUNT;
|
||||
@ -312,7 +312,7 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
|
||||
unsigned short port = htons(6881);
|
||||
char *write_ptr;
|
||||
ssize_t len;
|
||||
struct http_data *cookie = io_getcookie( sock );
|
||||
struct http_data *cookie = io_getcookie( sock );
|
||||
|
||||
/* This is to hack around stupid clients that send "announce ?info_hash" */
|
||||
if( read_ptr[-1] != '?' ) {
|
||||
@ -412,6 +412,9 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws,
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX DEBUG */
|
||||
stats_issue_event( EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ws->reply );
|
||||
|
||||
/* Scanned whole query string */
|
||||
if( !hash )
|
||||
return ws->reply_size = sprintf( ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e" );
|
||||
@ -488,14 +491,14 @@ ssize_t http_handle_request( const int64 sock, struct ot_workstruct *ws ) {
|
||||
*/
|
||||
reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf( ws->outbuf, 0, "%zd", ws->reply_size );
|
||||
ws->reply = ws->outbuf + reply_off;
|
||||
|
||||
|
||||
/* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete
|
||||
packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */
|
||||
ws->reply_size += 1 + sprintf( ws->reply, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", ws->reply_size );
|
||||
|
||||
/* 3. Finally we join both blocks neatly */
|
||||
ws->outbuf[ SUCCESS_HTTP_HEADER_LENGTH - 1 ] = '\n';
|
||||
|
||||
|
||||
http_senddata( sock, ws );
|
||||
return ws->reply_size;
|
||||
}
|
||||
|
60
ot_stats.c
60
ot_stats.c
@ -1,6 +1,6 @@
|
||||
/* This software was written by Dirk Engling <erdgeist@erdgeist.org>
|
||||
It is considered beerware. Prost. Skol. Cheers or whatever.
|
||||
|
||||
|
||||
$id$ */
|
||||
|
||||
/* System */
|
||||
@ -84,10 +84,10 @@ static int stat_increase_network_count( stats_network_node **node, int depth, ui
|
||||
return -1;
|
||||
memset( *node, 0, sizeof( stats_network_node ) );
|
||||
}
|
||||
|
||||
|
||||
if( depth < STATS_NETWORK_NODE_MAXDEPTH )
|
||||
return stat_increase_network_count( &(*node)->children[ foo ], depth+1, ip );
|
||||
|
||||
|
||||
(*node)->counters[ foo ]++;
|
||||
return 0;
|
||||
}
|
||||
@ -122,9 +122,9 @@ static int stats_shift_down_network_count( stats_network_node **node, int depth,
|
||||
static void stats_get_highscore_networks( stats_network_node *node, int depth, ot_ip6 node_value, int *scores, ot_ip6 *networks, int network_count ) {
|
||||
uint8_t *_node_value = (uint8_t*)node_value;
|
||||
int i;
|
||||
|
||||
|
||||
if( !node ) return;
|
||||
|
||||
|
||||
if( depth < STATS_NETWORK_NODE_MAXDEPTH ) {
|
||||
for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i )
|
||||
if( node->children[i] ) {
|
||||
@ -139,7 +139,7 @@ static void stats_get_highscore_networks( stats_network_node *node, int depth, o
|
||||
_node_value[depth] = i;
|
||||
while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j;
|
||||
--j;
|
||||
|
||||
|
||||
memcpy( scores, scores + 1, j * sizeof( *scores ) );
|
||||
memcpy( networks, networks + 1, j * sizeof( *networks ) );
|
||||
scores[ j ] = node->counters[ i ];
|
||||
@ -158,7 +158,7 @@ static size_t stats_return_busy_networks( char * reply ) {
|
||||
memset( networks, 0, sizeof( *networks ) * 256 );
|
||||
|
||||
stats_get_highscore_networks( stats_network_counters_root, 0, node_value, scores, networks, 256 );
|
||||
|
||||
|
||||
for( i=255; i>=0; --i) {
|
||||
r += sprintf( r, "%08i: ", scores[i] );
|
||||
r += fmt_ip6c( r, networks[i] );
|
||||
@ -195,10 +195,10 @@ size_t stats_top10_txt( char * reply ) {
|
||||
ot_record top10s[10], top10c[10];
|
||||
char *r = reply, hex_out[42];
|
||||
int idx, bucket;
|
||||
|
||||
|
||||
byte_zero( top10s, sizeof( top10s ) );
|
||||
byte_zero( top10c, sizeof( top10c ) );
|
||||
|
||||
|
||||
for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) {
|
||||
ot_vector *torrents_list = mutex_bucket_lock( bucket );
|
||||
for( j=0; j<torrents_list->size; ++j ) {
|
||||
@ -220,7 +220,7 @@ size_t stats_top10_txt( char * reply ) {
|
||||
if( !g_opentracker_running )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
r += sprintf( r, "Top 10 torrents by peers:\n" );
|
||||
for( idx=0; idx<10; ++idx )
|
||||
if( top10c[idx].torrent )
|
||||
@ -229,7 +229,7 @@ size_t stats_top10_txt( char * reply ) {
|
||||
for( idx=0; idx<10; ++idx )
|
||||
if( top10s[idx].torrent )
|
||||
r += sprintf( r, "\t%zd\t%s\n", top10s[idx].val, to_hex( hex_out, top10s[idx].torrent->hash) );
|
||||
|
||||
|
||||
return r - reply;
|
||||
}
|
||||
|
||||
@ -237,23 +237,23 @@ size_t stats_top10_txt( char * reply ) {
|
||||
malloc blocks
|
||||
*/
|
||||
static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh ) {
|
||||
|
||||
|
||||
#define NUM_TOPBITS 12
|
||||
#define NUM_LOWBITS (24-NUM_TOPBITS)
|
||||
#define NUM_BUFS (1<<NUM_TOPBITS)
|
||||
#define NUM_S24S (1<<NUM_LOWBITS)
|
||||
#define MSK_S24S (NUM_S24S-1)
|
||||
|
||||
|
||||
uint32_t *counts[ NUM_BUFS ];
|
||||
uint32_t slash24s[amount*2]; /* first dword amount, second dword subnet */
|
||||
size_t i, j, k, l;
|
||||
char *r = reply;
|
||||
|
||||
|
||||
byte_zero( counts, sizeof( counts ) );
|
||||
byte_zero( slash24s, amount * 2 * sizeof(uint32_t) );
|
||||
|
||||
|
||||
r += sprintf( r, "Stats for all /24s with more than %u announced torrents:\n\n", thresh );
|
||||
|
||||
|
||||
#if 0
|
||||
/* XXX: TOOD: Doesn't work yet with new peer storage model */
|
||||
for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) {
|
||||
@ -284,7 +284,7 @@ static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh )
|
||||
goto bailout_cleanup;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
k = l = 0; /* Debug: count allocated bufs */
|
||||
for( i=0; i < NUM_BUFS; ++i ) {
|
||||
uint32_t *count = counts[i];
|
||||
@ -308,20 +308,20 @@ static size_t stats_slash24s_txt( char * reply, size_t amount, uint32_t thresh )
|
||||
}
|
||||
free( count );
|
||||
}
|
||||
|
||||
|
||||
r += sprintf( r, "Allocated bufs: %zd, used s24s: %zd\n", k, l );
|
||||
|
||||
|
||||
for( i=0; i < amount; ++i )
|
||||
if( slash24s[ 2*i ] >= thresh ) {
|
||||
uint32_t ip = slash24s[ 2*i +1 ];
|
||||
r += sprintf( r, "% 10ld %d.%d.%d.0/24\n", (long)slash24s[ 2*i ], (int)(ip >> 16), (int)(255 & ( ip >> 8 )), (int)(ip & 255) );
|
||||
}
|
||||
|
||||
|
||||
return r - reply;
|
||||
|
||||
|
||||
for( i=0; i < NUM_BUFS; ++i )
|
||||
free( counts[i] );
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -395,9 +395,9 @@ static size_t stats_fullscrapes_mrtg( char * reply ) {
|
||||
|
||||
static size_t stats_peers_mrtg( char * reply ) {
|
||||
torrent_stats stats = {0,0,0};
|
||||
|
||||
|
||||
iterate_all_torrents( torrent_statter, (uintptr_t)&stats );
|
||||
|
||||
|
||||
return sprintf( reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker",
|
||||
stats.peer_count,
|
||||
stats.seed_count,
|
||||
@ -408,7 +408,7 @@ static size_t stats_peers_mrtg( char * reply ) {
|
||||
static size_t stats_torrents_mrtg( char * reply )
|
||||
{
|
||||
size_t torrent_count = mutex_get_torrent_count();
|
||||
|
||||
|
||||
return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker",
|
||||
torrent_count,
|
||||
(size_t)0,
|
||||
@ -426,7 +426,7 @@ static size_t stats_httperrors_txt ( char * reply ) {
|
||||
static size_t stats_return_renew_bucket( char * reply ) {
|
||||
char *r = reply;
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; i<OT_PEER_TIMEOUT; ++i )
|
||||
r+=sprintf(r,"%02i %llu\n", i, ot_renewed[i] );
|
||||
return r - reply;
|
||||
@ -526,12 +526,12 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) {
|
||||
|
||||
static void stats_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) {
|
||||
char *r;
|
||||
|
||||
|
||||
*iovec_entries = 0;
|
||||
*iovector = NULL;
|
||||
if( !( r = iovec_increase( iovec_entries, iovector, OT_STATS_TMPSIZE ) ) )
|
||||
return;
|
||||
|
||||
|
||||
switch( mode & TASK_TASK_MASK ) {
|
||||
case TASK_STATS_TORRENTS: r += stats_torrents_mrtg( r ); break;
|
||||
case TASK_STATS_PEERS: r += stats_peers_mrtg( r ); break;
|
||||
@ -607,9 +607,9 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event
|
||||
static void * stats_worker( void * args ) {
|
||||
int iovec_entries;
|
||||
struct iovec *iovector;
|
||||
|
||||
|
||||
args = args;
|
||||
|
||||
|
||||
while( 1 ) {
|
||||
ot_tasktype tasktype = TASK_STATS;
|
||||
ot_taskid taskid = mutex_workqueue_poptask( &tasktype );
|
||||
|
@ -41,6 +41,33 @@ void free_peerlist( ot_peerlist *peer_list ) {
|
||||
free( peer_list );
|
||||
}
|
||||
|
||||
void add_torrent_from_saved_state( ot_hash hash, ot_time base, size_t down_count ) {
|
||||
int exactmatch;
|
||||
ot_torrent *torrent;
|
||||
ot_vector *torrents_list = mutex_bucket_lock_by_hash( hash );
|
||||
|
||||
if( !accesslist_hashisvalid( hash ) )
|
||||
return mutex_bucket_unlock_by_hash( hash, 0 );
|
||||
|
||||
torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch );
|
||||
if( !torrent || exactmatch )
|
||||
return mutex_bucket_unlock_by_hash( hash, 0 );
|
||||
|
||||
/* Create a new torrent entry, then */
|
||||
memcpy( torrent->hash, hash, sizeof(ot_hash) );
|
||||
|
||||
if( !( torrent->peer_list = malloc( sizeof (ot_peerlist) ) ) ) {
|
||||
vector_remove_torrent( torrents_list, torrent );
|
||||
return mutex_bucket_unlock_by_hash( hash, 0 );
|
||||
}
|
||||
|
||||
byte_zero( torrent->peer_list, sizeof( ot_peerlist ) );
|
||||
torrent->peer_list->base = base;
|
||||
torrent->peer_list->down_count = down_count;
|
||||
|
||||
return mutex_bucket_unlock_by_hash( hash, 1 );
|
||||
}
|
||||
|
||||
size_t add_peer_to_torrent_and_return_peers( ot_hash hash, ot_peer *peer, PROTO_FLAG proto, size_t amount, char * reply ) {
|
||||
int exactmatch, delta_torrentcount = 0;
|
||||
size_t reply_size;
|
||||
@ -375,7 +402,7 @@ void trackerlogic_init( ) {
|
||||
void trackerlogic_deinit( void ) {
|
||||
int bucket, delta_torrentcount = 0;
|
||||
size_t j;
|
||||
|
||||
|
||||
/* Free all torrents... */
|
||||
for(bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) {
|
||||
ot_vector *torrents_list = mutex_bucket_lock( bucket );
|
||||
|
@ -147,6 +147,7 @@ size_t add_peer_to_torrent_and_return_peers( ot_hash hash, ot_peer *peer, PROTO
|
||||
size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROTO_FLAG proto );
|
||||
size_t return_tcp_scrape_for_torrent( ot_hash *hash, int amount, char *reply );
|
||||
size_t return_udp_scrape_for_torrent( ot_hash hash, char *reply );
|
||||
void add_torrent_from_saved_state( ot_hash hash, ot_time base, size_t down_count );
|
||||
|
||||
/* torrent iterator */
|
||||
void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data ), uintptr_t data );
|
||||
|
Loading…
Reference in New Issue
Block a user