diff options
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | opentracker.c | 2 | ||||
-rw-r--r-- | ot_http.c | 2 | ||||
-rw-r--r-- | ot_mutex.h | 1 | ||||
-rw-r--r-- | ot_stats.c | 111 | ||||
-rw-r--r-- | ot_stats.h | 2 | ||||
-rw-r--r-- | ot_udp.c | 2 |
7 files changed, 117 insertions, 4 deletions
@@ -25,6 +25,7 @@ BINDIR?=$(PREFIX)/bin | |||
25 | #FEATURES+=-DWANT_UTORRENT1600_WORKAROUND | 25 | #FEATURES+=-DWANT_UTORRENT1600_WORKAROUND |
26 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING | 26 | #FEATURES+=-DWANT_IP_FROM_QUERY_STRING |
27 | #FEATURES+=-DWANT_COMPRESSION_GZIP | 27 | #FEATURES+=-DWANT_COMPRESSION_GZIP |
28 | #FEATURES+=-DWANT_LOG_NETWORKS | ||
28 | #FEATURES+=-D_DEBUG_HTTPERROR | 29 | #FEATURES+=-D_DEBUG_HTTPERROR |
29 | 30 | ||
30 | OPTS_debug=-g -ggdb #-pg # -fprofile-arcs -ftest-coverage | 31 | OPTS_debug=-g -ggdb #-pg # -fprofile-arcs -ftest-coverage |
diff --git a/opentracker.c b/opentracker.c index a3aa827..21b3d87 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -167,7 +167,7 @@ static void handle_accept( const int64 serversocket ) { | |||
167 | memset( h, 0, sizeof( struct http_data ) ); | 167 | memset( h, 0, sizeof( struct http_data ) ); |
168 | memmove( h->ip, ip, sizeof( ip ) ); | 168 | memmove( h->ip, ip, sizeof( ip ) ); |
169 | 169 | ||
170 | stats_issue_event( EVENT_ACCEPT, 1, 0); | 170 | stats_issue_event( EVENT_ACCEPT, 1, ntohl(*(uint32_t*)ip)); |
171 | 171 | ||
172 | /* That breaks taia encapsulation. But there is no way to take system | 172 | /* That breaks taia encapsulation. But there is no way to take system |
173 | time this often in FreeBSD and libowfat does not allow to set unix time */ | 173 | time this often in FreeBSD and libowfat does not allow to set unix time */ |
@@ -259,6 +259,8 @@ static ssize_t http_handle_stats( const int64 client_socket, char *data, char *d | |||
259 | mode = TASK_STATS_TORADDREM; | 259 | mode = TASK_STATS_TORADDREM; |
260 | else if( !byte_diff(data,4,"vers")) | 260 | else if( !byte_diff(data,4,"vers")) |
261 | mode = TASK_STATS_VERSION; | 261 | mode = TASK_STATS_VERSION; |
262 | else if( !byte_diff(data,4,"busy")) | ||
263 | mode = TASK_STATS_BUSY_NETWORKS; | ||
262 | else | 264 | else |
263 | HTTPERROR_400_PARAM; | 265 | HTTPERROR_400_PARAM; |
264 | break; | 266 | break; |
@@ -29,6 +29,7 @@ typedef enum { | |||
29 | TASK_STATS_STARTSTOP = 0x000a, | 29 | TASK_STATS_STARTSTOP = 0x000a, |
30 | TASK_STATS_TORADDREM = 0x000b, | 30 | TASK_STATS_TORADDREM = 0x000b, |
31 | TASK_STATS_VERSION = 0x000c, | 31 | TASK_STATS_VERSION = 0x000c, |
32 | TASK_STATS_BUSY_NETWORKS = 0x000d, | ||
32 | 33 | ||
33 | TASK_STATS_SLASH24S = 0x0100, | 34 | TASK_STATS_SLASH24S = 0x0100, |
34 | 35 | ||
@@ -43,6 +43,110 @@ static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; | |||
43 | 43 | ||
44 | static time_t ot_start_time; | 44 | static time_t ot_start_time; |
45 | 45 | ||
46 | #ifdef WANT_LOG_NETWORKS | ||
47 | #define STATS_NETWORK_NODE_BITWIDTH 8 | ||
48 | #define STATS_NETWORK_NODE_MAXDEPTH 3 | ||
49 | |||
50 | #define STATS_NETWORK_NODE_BITMASK ((1<<STATS_NETWORK_NODE_BITWIDTH)-1) | ||
51 | #define STATS_NETWORK_NODE_COUNT (1<<STATS_NETWORK_NODE_BITWIDTH) | ||
52 | |||
53 | typedef union stats_network_node stats_network_node; | ||
54 | union stats_network_node { | ||
55 | int counters[STATS_NETWORK_NODE_COUNT]; | ||
56 | stats_network_node *children[STATS_NETWORK_NODE_COUNT]; | ||
57 | }; | ||
58 | |||
59 | static stats_network_node *stats_network_counters_root = NULL; | ||
60 | |||
61 | static int stat_increase_network_count( stats_network_node **node, int depth, uint32_t ip ) { | ||
62 | int foo = ( ip >> ( 32 - STATS_NETWORK_NODE_BITWIDTH * ( ++depth ) ) ) & STATS_NETWORK_NODE_BITMASK; | ||
63 | |||
64 | if( !*node ) { | ||
65 | *node = malloc( sizeof( stats_network_node ) ); | ||
66 | if( !*node ) | ||
67 | return -1; | ||
68 | memset( *node, 0, sizeof( stats_network_node ) ); | ||
69 | } | ||
70 | |||
71 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) | ||
72 | return stat_increase_network_count( &(*node)->children[ foo ], depth, ip ); | ||
73 | |||
74 | (*node)->counters[ foo ]++; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) { | ||
79 | int i, rest = 0; | ||
80 | if( !*node ) return 0; | ||
81 | |||
82 | if( ++depth == STATS_NETWORK_NODE_MAXDEPTH ) | ||
83 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
84 | rest += ((*node)->counters[i]>>=shift); | ||
85 | return rest; | ||
86 | } | ||
87 | |||
88 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
89 | stats_network_node **childnode = &(*node)->children[i]; | ||
90 | int rest_val; | ||
91 | |||
92 | if( !*childnode ) continue; | ||
93 | |||
94 | rest += rest_val = stats_shift_down_network_count( childnode, depth, shift ); | ||
95 | |||
96 | if( rest_val ) continue; | ||
97 | |||
98 | free( (*node)->children[i] ); | ||
99 | (*node)->children[i] = NULL; | ||
100 | } | ||
101 | |||
102 | return rest; | ||
103 | } | ||
104 | |||
105 | static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) { | ||
106 | int i; | ||
107 | |||
108 | if( !node ) return; | ||
109 | |||
110 | if( !depth++ ) { | ||
111 | memset( scores, 0, sizeof( *scores ) * network_count ); | ||
112 | memset( networks, 0, sizeof( *networks ) * network_count ); | ||
113 | } | ||
114 | |||
115 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) { | ||
116 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) | ||
117 | if( node->children[i] ) | ||
118 | stats_get_highscore_networks( node->children[i], depth, node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ), scores, networks, network_count ); | ||
119 | } else | ||
120 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
121 | int j=1; | ||
122 | if( node->counters[i] <= scores[0] ) continue; | ||
123 | |||
124 | while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j; | ||
125 | --j; | ||
126 | |||
127 | memmove( scores, scores + 1, j * sizeof( *scores ) ); | ||
128 | memmove( networks, networks + 1, j * sizeof( *networks ) ); | ||
129 | scores[ j ] = node->counters[ i ]; | ||
130 | networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static size_t stats_return_busy_networks( char * reply ) { | ||
135 | uint32_t networks[16]; | ||
136 | int scores[16]; | ||
137 | int i; | ||
138 | char * r = reply; | ||
139 | |||
140 | stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 ); | ||
141 | |||
142 | for( i=15; i>=0; ++i) | ||
143 | r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff ); | ||
144 | |||
145 | return r - reply; | ||
146 | } | ||
147 | |||
148 | #endif | ||
149 | |||
46 | /* Converter function from memory to human readable hex strings */ | 150 | /* Converter function from memory to human readable hex strings */ |
47 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} | 151 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} |
48 | 152 | ||
@@ -377,15 +481,20 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { | |||
377 | return stats_httperrors_txt( reply ); | 481 | return stats_httperrors_txt( reply ); |
378 | case TASK_STATS_VERSION: | 482 | case TASK_STATS_VERSION: |
379 | return stats_return_tracker_version( reply ); | 483 | return stats_return_tracker_version( reply ); |
484 | case TASK_STATS_BUSY_NETWORKS: | ||
485 | return stats_return_busy_networks( reply ); | ||
380 | default: | 486 | default: |
381 | return 0; | 487 | return 0; |
382 | } | 488 | } |
383 | } | 489 | } |
384 | 490 | ||
385 | void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) { | 491 | void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ) { |
386 | switch( event ) { | 492 | switch( event ) { |
387 | case EVENT_ACCEPT: | 493 | case EVENT_ACCEPT: |
388 | if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; | 494 | if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; |
495 | #ifdef WANT_LOG_NETWORKS | ||
496 | stat_increase_network_count( &stats_network_counters_root, 0, event_data ); | ||
497 | #endif | ||
389 | break; | 498 | break; |
390 | case EVENT_ANNOUNCE: | 499 | case EVENT_ANNOUNCE: |
391 | if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; | 500 | if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; |
@@ -34,7 +34,7 @@ enum { | |||
34 | CODE_HTTPERROR_COUNT | 34 | CODE_HTTPERROR_COUNT |
35 | }; | 35 | }; |
36 | 36 | ||
37 | void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ); | 37 | void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ); |
38 | size_t return_stats_for_tracker( char *reply, int mode, int format ); | 38 | size_t return_stats_for_tracker( char *reply, int mode, int format ); |
39 | size_t stats_return_tracker_version( char *reply ); | 39 | size_t stats_return_tracker_version( char *reply ); |
40 | void stats_init( ); | 40 | void stats_init( ); |
@@ -54,7 +54,7 @@ void handle_udp4( int64 serversocket ) { | |||
54 | 54 | ||
55 | r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport); | 55 | r = socket_recv4( serversocket, static_inbuf, sizeof( static_inbuf ), remoteip, &remoteport); |
56 | 56 | ||
57 | stats_issue_event( EVENT_ACCEPT, 0, 0 ); | 57 | stats_issue_event( EVENT_ACCEPT, 0, ntohl(*(uint32_t*)remoteip) ); |
58 | stats_issue_event( EVENT_READ, 0, r ); | 58 | stats_issue_event( EVENT_READ, 0, r ); |
59 | 59 | ||
60 | /* Minimum udp tracker packet size, also catches error */ | 60 | /* Minimum udp tracker packet size, also catches error */ |