summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--opentracker.c2
-rw-r--r--ot_http.c2
-rw-r--r--ot_mutex.h1
-rw-r--r--ot_stats.c111
-rw-r--r--ot_stats.h2
-rw-r--r--ot_udp.c2
7 files changed, 117 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 3d4f97b..cf42a68 100644
--- a/Makefile
+++ b/Makefile
@@ -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
30OPTS_debug=-g -ggdb #-pg # -fprofile-arcs -ftest-coverage 31OPTS_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 */
diff --git a/ot_http.c b/ot_http.c
index 7b0e7ae..682195b 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -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;
diff --git a/ot_mutex.h b/ot_mutex.h
index dcb50eb..17cb5b4 100644
--- a/ot_mutex.h
+++ b/ot_mutex.h
@@ -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
diff --git a/ot_stats.c b/ot_stats.c
index 6113275..81ff487 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -43,6 +43,110 @@ static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT];
43 43
44static time_t ot_start_time; 44static 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
53typedef union stats_network_node stats_network_node;
54union stats_network_node {
55 int counters[STATS_NETWORK_NODE_COUNT];
56 stats_network_node *children[STATS_NETWORK_NODE_COUNT];
57};
58
59static stats_network_node *stats_network_counters_root = NULL;
60
61static 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
78static 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
105static 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
134static 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 */
47static 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;} 151static 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
385void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) { 491void 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++;
diff --git a/ot_stats.h b/ot_stats.h
index c07a950..8cc7a5b 100644
--- a/ot_stats.h
+++ b/ot_stats.h
@@ -34,7 +34,7 @@ enum {
34 CODE_HTTPERROR_COUNT 34 CODE_HTTPERROR_COUNT
35}; 35};
36 36
37void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ); 37void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data );
38size_t return_stats_for_tracker( char *reply, int mode, int format ); 38size_t return_stats_for_tracker( char *reply, int mode, int format );
39size_t stats_return_tracker_version( char *reply ); 39size_t stats_return_tracker_version( char *reply );
40void stats_init( ); 40void stats_init( );
diff --git a/ot_udp.c b/ot_udp.c
index e1af2fe..3cafd35 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -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 */