diff --git a/opentracker.c b/opentracker.c index b839efc..c67e331 100644 --- a/opentracker.c +++ b/opentracker.c @@ -135,12 +135,10 @@ static ssize_t handle_read( const int64 sock, struct ot_workstruct *ws ) { array_catb( &cookie->data.request, ws->inbuf, byte_count ); - if( array_failed( &cookie->data.request ) ) + if( array_failed( &cookie->data.request ) || + array_bytes( &cookie->data.request ) > 8192 ) return http_issue_error( sock, ws, CODE_HTTPERROR_500 ); - if( array_bytes( &cookie->data.request ) > 8192 ) - return http_issue_error( sock, ws, CODE_HTTPERROR_500 ); - if( !memchr( array_start( &cookie->data.request ), '\n', array_bytes( &cookie->data.request ) ) ) return 0; @@ -369,6 +367,11 @@ int parse_configfile( char * config_filename ) { } else if(!byte_diff(p, 12, "access.stats" ) && isspace(p[12])) { if( !scan_ip6( p+13, tmpip )) goto parse_error; accesslist_blessip( tmpip, OT_PERMISSION_MAY_STAT ); +#endif +#ifdef WANT_IP_FROM_PROXY + } else if(!byte_diff(p, 12, "access.proxy" ) && isspace(p[12])) { + if( !scan_ip6( p+13, tmpip )) goto parse_error; + accesslist_blessip( tmpip, OT_PERMISSION_MAY_PROXY ); #endif } else if(!byte_diff(p, 20, "tracker.redirect_url" ) && isspace(p[20])) { set_config_option( &g_redirecturl, p+21 ); diff --git a/ot_accesslist.c b/ot_accesslist.c index 304b3f1..631ab88 100644 --- a/ot_accesslist.c +++ b/ot_accesslist.c @@ -124,6 +124,7 @@ int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ) { 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" ); + if( permissions & OT_PERMISSION_MAY_PROXY ) off += snprintf( _debug+off, 512-off, " may_proxy" ); if( !permissions ) off += snprintf( _debug+off, sizeof(_debug)-off, " nothing\n" ); _debug[off++] = '.'; write( 2, _debug, off ); diff --git a/ot_accesslist.h b/ot_accesslist.h index 836a233..5954a4a 100644 --- a/ot_accesslist.h +++ b/ot_accesslist.h @@ -27,7 +27,8 @@ extern char *g_accesslist_filename; typedef enum { OT_PERMISSION_MAY_FULLSCRAPE = 0x1, OT_PERMISSION_MAY_STAT = 0x2, - OT_PERMISSION_MAY_LIVESYNC = 0x4 + OT_PERMISSION_MAY_LIVESYNC = 0x4, + OT_PERMISSION_MAY_PROXY = 0x8 } ot_permissions; int accesslist_blessip( ot_ip6 ip, ot_permissions permissions ); diff --git a/ot_http.c b/ot_http.c index 971d81d..de57dad 100644 --- a/ot_http.c +++ b/ot_http.c @@ -306,13 +306,14 @@ static ot_keywords keywords_announce[] = { { "port", 1 }, { "left", 2 }, { "even { NULL, -3 } }; static ot_keywords keywords_announce_event[] = { { "completed", 1 }, { "stopped", 2 }, { NULL, -3 } }; static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, char *read_ptr ) { - int numwant, tmp, scanon; - ot_peer peer; - ot_hash *hash = NULL; - unsigned short port = htons(6881); - char *write_ptr; - ssize_t len; - + int numwant, tmp, scanon; + ot_peer peer; + ot_hash *hash = NULL; + unsigned short port = htons(6881); + char *write_ptr; + ssize_t len; + struct http_data *cookie = io_getcookie( sock ); + /* This is to hack around stupid clients that send "announce ?info_hash" */ if( read_ptr[-1] != '?' ) { while( ( *read_ptr != '?' ) && ( *read_ptr != '\n' ) ) ++read_ptr; @@ -320,7 +321,33 @@ static ssize_t http_handle_announce( const int64 sock, struct ot_workstruct *ws, ++read_ptr; } - OT_SETIP( &peer, ((struct http_data*)io_getcookie( sock ) )->ip ); +#ifdef WANT_IP_FROM_PROXY + if( accesslist_isblessed( cookie->ip, OT_PERMISSION_MAY_PROXY ) ) { + ot_ip6 proxied_ip; + char *fwd, *fwd_new = ws->request; + + /* Zero terminate for string routines. Normally we'd only overwrite bollocks */ + ws->request[ws->request_size-1] = 0; + + /* Find last occurence of the forwarded header */ + do { + fwd = fwd_new; + fwd_new = strcasestr( fwd_new, "\nX-Forwarded-For:" ); + } while( fwd_new ); + + /* Skip spaces between : and the ip address */ + if( fwd ) { + fwd += 18; /* sizeof( "\nX-Forwarded-For:" ) */ + while( *fwd == ' ' ) ++fwd; + } + + if( fwd && scan_ip6( fwd, proxied_ip ) ) + OT_SETIP( &peer, proxied_ip ); + else + OT_SETIP( &peer, cookie->ip ); + } +#endif + OT_SETIP( &peer, cookie->ip ); OT_SETPORT( &peer, &port ); OT_PEERFLAG( &peer ) = 0; numwant = 50; diff --git a/ot_mutex.c b/ot_mutex.c index 925eb27..2052ffa 100644 --- a/ot_mutex.c +++ b/ot_mutex.c @@ -18,6 +18,7 @@ /* Opentracker */ #include "trackerlogic.h" #include "ot_mutex.h" +#include "ot_stats.h" /* #define MTX_DBG( STRING ) fprintf( stderr, STRING ) */ #define MTX_DBG( STRING ) @@ -47,8 +48,10 @@ static int bucket_check( int bucket ) { /* See, if bucket is already locked */ for( i=0; i - It is considered beerware. Prost. Skol. Cheers or whatever. - - $id$ */ + It is considered beerware. Prost. Skol. Cheers or whatever. + + $id$ */ /* System */ #include @@ -50,12 +50,13 @@ static unsigned long long ot_full_scrape_size = 0; static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; static unsigned long long ot_renewed[OT_PEER_TIMEOUT]; static unsigned long long ot_overall_sync_count; +static unsigned long long ot_overall_stall_count; static time_t ot_start_time; #ifdef WANT_LOG_NETWORKS #define STATS_NETWORK_NODE_BITWIDTH 8 -#define STATS_NETWORK_NODE_MAXDEPTH 3 +#define STATS_NETWORK_NODE_MAXDEPTH 16 #define STATS_NETWORK_NODE_BITMASK ((1<> ( 32 - STATS_NETWORK_NODE_BITWIDTH * ( ++depth ) ) ) & STATS_NETWORK_NODE_BITMASK; - +static int stat_increase_network_count( stats_network_node **node, int depth, uintptr_t ip ) { + ot_ip6 *_ip = (ot_ip6*)ip; + int foo = (*_ip)[depth]; + if( !*node ) { *node = malloc( sizeof( stats_network_node ) ); if( !*node ) return -1; memset( *node, 0, sizeof( stats_network_node ) ); } - + if( depth < STATS_NETWORK_NODE_MAXDEPTH ) return stat_increase_network_count( &(*node)->children[ foo ], depth, ip ); - + (*node)->counters[ foo ]++; return 0; } @@ -88,40 +90,40 @@ static int stat_increase_network_count( stats_network_node **node, int depth, ui static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) { int i, rest = 0; if( !*node ) return 0; - + if( ++depth == STATS_NETWORK_NODE_MAXDEPTH ) for( i=0; icounters[i]>>=shift); - return rest; - } - + return rest; + } + for( i=0; ichildren[i]; int rest_val; - + if( !*childnode ) continue; - + rest += rest_val = stats_shift_down_network_count( childnode, depth, shift ); - + if( rest_val ) continue; - + free( (*node)->children[i] ); (*node)->children[i] = NULL; } - + return rest; } static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) { int i; - + if( !node ) return; - + if( !depth++ ) { memset( scores, 0, sizeof( *scores ) * network_count ); memset( networks, 0, sizeof( *networks ) * network_count ); } - + if( depth < STATS_NETWORK_NODE_MAXDEPTH ) { for( i=0; ichildren[i] ) @@ -130,15 +132,15 @@ static void stats_get_highscore_networks( stats_network_node *node, int depth, u for( i=0; icounters[i] <= scores[0] ) continue; - + while( (jcounters[i]>scores[j] ) ) ++j; --j; - + memcpy( scores, scores + 1, j * sizeof( *scores ) ); memcpy( networks, networks + 1, j * sizeof( *networks ) ); scores[ j ] = node->counters[ i ]; networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); - } + } } static size_t stats_return_busy_networks( char * reply ) { @@ -146,17 +148,31 @@ static size_t stats_return_busy_networks( char * reply ) { int scores[16]; int i; char * r = reply; - + stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 ); - + for( i=15; i>=0; --i) r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff ); - + return r - reply; } #endif +typedef struct { + unsigned long long torrent_count; + unsigned long long peer_count; + unsigned long long seed_count; +} torrent_stats; + +static int torrent_statter( ot_torrent *torrent, uintptr_t data ) { + torrent_stats *stats = (torrent_stats*)data; + stats->torrent_count++; + stats->peer_count += torrent->peer_list->peer_count; + stats->seed_count += torrent->peer_list->seed_count; + return 0; +} + /* Converter function from memory to human readable hex strings */ static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d>4];*d++=m[*s++&15];}*d=0;return t;} @@ -168,10 +184,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; bucketsize; ++j ) { @@ -193,7 +209,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 ) @@ -202,31 +218,31 @@ 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; } /* This function collects 4096 /24s in 4096 possible - malloc blocks -*/ + 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<= 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; } /* struct { - size_t size - size_t space - size_t count + size_t size + size_t space + size_t count } */ @@ -313,105 +329,95 @@ static unsigned long events_per_time( unsigned long long events, time_t t ) { static size_t stats_connections_mrtg( char * reply ) { ot_time t = time( NULL ) - ot_start_time; return sprintf( reply, - "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", - ot_overall_tcp_connections+ot_overall_udp_connections, - ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, - (int)t, - (int)(t / 3600), - events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), - events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) - ); + "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", + ot_overall_tcp_connections+ot_overall_udp_connections, + ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, + (int)t, + (int)(t / 3600), + events_per_time( ot_overall_tcp_connections+ot_overall_udp_connections, t ), + events_per_time( ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) + ); } static size_t stats_udpconnections_mrtg( char * reply ) { ot_time t = time( NULL ) - ot_start_time; return sprintf( reply, - "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", - ot_overall_udp_connections, - ot_overall_udp_successfulannounces+ot_overall_udp_connects, - (int)t, - (int)(t / 3600), - events_per_time( ot_overall_udp_connections, t ), - events_per_time( ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) - ); + "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", + ot_overall_udp_connections, + ot_overall_udp_successfulannounces+ot_overall_udp_connects, + (int)t, + (int)(t / 3600), + events_per_time( ot_overall_udp_connections, t ), + events_per_time( ot_overall_udp_successfulannounces+ot_overall_udp_connects, t ) + ); } static size_t stats_tcpconnections_mrtg( char * reply ) { time_t t = time( NULL ) - ot_start_time; return sprintf( reply, - "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", - ot_overall_tcp_connections, - ot_overall_tcp_successfulannounces, - (int)t, - (int)(t / 3600), - events_per_time( ot_overall_tcp_connections, t ), - events_per_time( ot_overall_tcp_successfulannounces, t ) - ); + "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", + ot_overall_tcp_connections, + ot_overall_tcp_successfulannounces, + (int)t, + (int)(t / 3600), + events_per_time( ot_overall_tcp_connections, t ), + events_per_time( ot_overall_tcp_successfulannounces, t ) + ); } static size_t stats_scrape_mrtg( char * reply ) { time_t t = time( NULL ) - ot_start_time; return sprintf( reply, - "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", - ot_overall_tcp_successfulscrapes, - ot_overall_udp_successfulscrapes, - (int)t, - (int)(t / 3600), - events_per_time( (ot_overall_tcp_successfulscrapes+ot_overall_udp_successfulscrapes), t ) - ); + "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", + ot_overall_tcp_successfulscrapes, + ot_overall_udp_successfulscrapes, + (int)t, + (int)(t / 3600), + events_per_time( (ot_overall_tcp_successfulscrapes+ot_overall_udp_successfulscrapes), t ) + ); } static size_t stats_fullscrapes_mrtg( char * reply ) { ot_time t = time( NULL ) - ot_start_time; return sprintf( reply, - "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", - ot_full_scrape_count * 1000, - ot_full_scrape_size, - (int)t, - (int)(t / 3600), - events_per_time( ot_full_scrape_count, t ), - events_per_time( ot_full_scrape_size, t ) - ); + "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.", + ot_full_scrape_count * 1000, + ot_full_scrape_size, + (int)t, + (int)(t / 3600), + events_per_time( ot_full_scrape_count, t ), + events_per_time( ot_full_scrape_size, t ) + ); } static size_t stats_peers_mrtg( char * reply ) { - size_t torrent_count = 0, peer_count = 0, seed_count = 0, j; - int bucket; - - for( bucket=0; bucketsize; - for( j=0; jsize; ++j ) { - ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[j] ).peer_list; - peer_count += peer_list->peer_count; seed_count += peer_list->seed_count; - } - mutex_bucket_unlock( bucket, 0 ); - if( !g_opentracker_running ) - return 0; - } - return sprintf( reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", - peer_count, - seed_count, - torrent_count - ); + 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, + stats.torrent_count + ); } static size_t stats_startstop_mrtg( char * reply ) { size_t torrent_count = mutex_get_torrent_count(); - + return sprintf( reply, "%zd\n%zd\nopentracker handling %zd torrents\nopentracker", - (size_t)0, - (size_t)0, - torrent_count - ); + (size_t)0, + (size_t)0, + torrent_count + ); } static size_t stats_toraddrem_mrtg( char * reply ) { size_t peer_count = 0, j; int bucket; - + for( bucket=0; bucket\n" ); + r += sprintf( r, " %llu\n", (unsigned long long)(time( NULL ) - ot_start_time) ); + r += sprintf( r, " %zd\n", mutex_get_torrent_count() ); + /* r += sprintf( r, " %llu\n", ); */ + + r += sprintf( reply, "" ); + return r - reply; } extern const char @@ -480,9 +496,9 @@ extern const char size_t stats_return_tracker_version( char *reply ) { return sprintf( reply, "%s%s%s%s%s%s%s%s%s%s%s%s%s", - g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, - g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, - g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c ); + g_version_opentracker_c, g_version_accesslist_c, g_version_clean_c, g_version_fullscrape_c, g_version_http_c, + g_version_iovec_c, g_version_mutex_c, g_version_stats_c, g_version_udp_c, g_version_vector_c, + g_version_scan_urlencoded_query_c, g_version_trackerlogic_c, g_version_livesync_c ); } size_t return_stats_for_tracker( char *reply, int mode, int format ) { @@ -509,7 +525,7 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { case TASK_STATS_RENEW: return stats_return_renew_bucket( reply ); case TASK_STATS_SYNCS: - return stats_return_sync_mrtg( reply ); + return stats_return_sync_mrtg( reply ); #ifdef WANT_LOG_NETWORKS case TASK_STATS_BUSY_NETWORKS: return stats_return_busy_networks( reply ); @@ -521,12 +537,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; @@ -560,26 +576,26 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event ot_full_scrape_size += event_data; break; case EVENT_FULLSCRAPE_REQUEST: - { - ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ - char _debug[512]; - int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); - off += fmt_ip6( _debug+off, *ip ); - off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); - write( 2, _debug, off ); - ot_full_scrape_request_count++; - } + { + ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ + char _debug[512]; + int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); + off += fmt_ip6( _debug+off, *ip ); + off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); + write( 2, _debug, off ); + ot_full_scrape_request_count++; + } break; case EVENT_FULLSCRAPE_REQUEST_GZIP: - { - ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ - char _debug[512]; - int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); - off += fmt_ip6(_debug+off, *ip ); - off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); - write( 2, _debug, off ); - ot_full_scrape_request_count++; - } + { + ot_ip6 *ip = (ot_ip6*)event_data; /* ugly hack to transfer ip to stats */ + char _debug[512]; + int off = snprintf( _debug, sizeof(_debug), "[%08d] scrp: ", (unsigned int)(g_now_seconds - ot_start_time)/60 ); + off += fmt_ip6(_debug+off, *ip ); + off += snprintf( _debug+off, sizeof(_debug)-off, " - FULL SCRAPE\n" ); + write( 2, _debug, off ); + ot_full_scrape_request_count++; + } break; case EVENT_FAILED: ot_failed_request_counts[event_data]++; @@ -590,6 +606,9 @@ void stats_issue_event( ot_status_event event, PROTO_FLAG proto, uintptr_t event case EVENT_SYNC: ot_overall_sync_count+=event_data; break; + case EVENT_BUCKET_LOCKED: + ot_overall_stall_count++; + break; default: break; } @@ -598,9 +617,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 ); diff --git a/ot_stats.h b/ot_stats.h index b8a64a1..7753947 100644 --- a/ot_stats.h +++ b/ot_stats.h @@ -17,7 +17,8 @@ typedef enum { EVENT_FULLSCRAPE_REQUEST, EVENT_FULLSCRAPE_REQUEST_GZIP, EVENT_FULLSCRAPE, /* TCP only */ - EVENT_FAILED + EVENT_FAILED, + EVENT_BUCKET_LOCKED } ot_status_event; enum { diff --git a/trackerlogic.c b/trackerlogic.c index 249a2a0..8ebaa46 100644 --- a/trackerlogic.c +++ b/trackerlogic.c @@ -337,6 +337,23 @@ size_t remove_peer_from_torrent( ot_hash hash, ot_peer *peer, char *reply, PROTO return reply_size; } +void iterate_all_torrents( int (*for_each)( ot_torrent* torrent, uintptr_t data ), uintptr_t data ) { + int bucket; + size_t j; + + for( bucket=0; bucketdata); + + for( j=0; jsize; ++j ) + if( for_each( torrents + j, data ) ) + break; + + mutex_bucket_unlock( bucket, 0 ); + if( !g_opentracker_running ) return; + } +} + void exerr( char * message ) { fprintf( stderr, "%s\n", message ); exit( 111 ); @@ -358,7 +375,7 @@ void trackerlogic_init( ) { void trackerlogic_deinit( void ) { int bucket, delta_torrentcount = 0; size_t j; - + /* Free all torrents... */ for(bucket=0; bucket