summaryrefslogtreecommitdiff
path: root/ot_stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_stats.c')
-rw-r--r--ot_stats.c335
1 files changed, 160 insertions, 175 deletions
diff --git a/ot_stats.c b/ot_stats.c
index 7945f4e..45dc8db 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -16,15 +16,13 @@
16#include <syslog.h> 16#include <syslog.h>
17#endif 17#endif
18 18
19/* Libowfat */
20#include "io.h"
21
22/* Opentracker */ 19/* Opentracker */
23#include "ot_accesslist.h" 20#include "ot_accesslist.h"
24#include "ot_hex.h" 21#include "ot_hex.h"
25#include "ot_iovec.h" 22#include "ot_iovec.h"
26#include "ot_ip.h" 23#include "ot_ip.h"
27#include "ot_mutex.h" 24#include "ot_mutex.h"
25#include "ot_fmt.h"
28#include "ot_stats.h" 26#include "ot_stats.h"
29#include "trackerlogic.h" 27#include "trackerlogic.h"
30 28
@@ -53,7 +51,7 @@ static unsigned long long ot_full_scrape_count;
53static unsigned long long ot_full_scrape_request_count; 51static unsigned long long ot_full_scrape_request_count;
54static unsigned long long ot_full_scrape_size; 52static unsigned long long ot_full_scrape_size;
55static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; 53static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT];
56static char *ot_failed_request_names[] = { 54static const char *ot_failed_request_names[] = {
57 "302 Redirect", "400 Parse Error", "400 Invalid Parameter", "400 Invalid Parameter (compact=0)", "400 Not Modest", 55 "302 Redirect", "400 Parse Error", "400 Invalid Parameter", "400 Invalid Parameter (compact=0)", "400 Not Modest",
58 "402 Payment Required", "403 Access Denied", "404 Not found", "500 Internal Server Error"}; 56 "402 Payment Required", "403 Access Denied", "404 Not found", "500 Internal Server Error"};
59static unsigned long long ot_renewed[OT_PEER_TIMEOUT]; 57static unsigned long long ot_renewed[OT_PEER_TIMEOUT];
@@ -178,8 +176,8 @@ static size_t stats_get_highscore_networks(stats_network_node *node, int depth,
178 ++j; 176 ++j;
179 --j; 177 --j;
180 178
181 memcpy(scores, scores + 1, j * sizeof(*scores)); 179 memmove(scores, scores + 1, j * sizeof(*scores));
182 memcpy(networks, networks + 1, j * sizeof(*networks)); 180 memmove(networks, networks + 1, j * sizeof(*networks));
183 scores[j] = node_score; 181 scores[j] = node_score;
184 memcpy(networks + j, node_value, sizeof(*networks)); 182 memcpy(networks + j, node_value, sizeof(*networks));
185 } 183 }
@@ -187,12 +185,11 @@ static size_t stats_get_highscore_networks(stats_network_node *node, int depth,
187 return score; 185 return score;
188} 186}
189 187
190static size_t stats_return_busy_networks(char *reply, stats_network_node *tree, size_t amount, int limit) { 188static void stats_return_busy_networks(char **reply, const char *reply_end, stats_network_node *tree, size_t amount, int limit) {
191 ot_ip6 networks[amount]; 189 ot_ip6 networks[amount];
192 ot_ip6 node_value; 190 ot_ip6 node_value;
193 size_t scores[amount]; 191 size_t scores[amount];
194 size_t i; 192 size_t i;
195 char *r = reply;
196 193
197 memset(scores, 0, sizeof(scores)); 194 memset(scores, 0, sizeof(scores));
198 memset(networks, 0, sizeof(networks)); 195 memset(networks, 0, sizeof(networks));
@@ -200,28 +197,21 @@ static size_t stats_return_busy_networks(char *reply, stats_network_node *tree,
200 197
201 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit); 198 stats_get_highscore_networks(tree, 0, node_value, scores, networks, amount, limit);
202 199
203 r += sprintf(r, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH); 200 fmt_append(reply, reply_end, "Networks, limit /%d:\n", limit + STATS_NETWORK_NODE_BITWIDTH);
204 for (i = amount; i > 0; --i) { 201 for (i = amount; i > 0; --i) {
205 if (scores[i - 1]) { 202 if (scores[i - 1]) {
206 r += sprintf(r, "%08zd: ", scores[i - 1]); 203 char ip_readable[64];
207 // #ifdef WANT_V6 204
208 r += ip_format(r, networks[i - 1]); 205 ip_readable[ip_format(ip_readable, networks[i - 1])] = 0;
209#if 0 206 fmt_append(reply, reply_end, "%08zd: %s\n", scores[i - 1], ip_readable);
210 // XXX
211 r += fmt_ip4( r, networks[i - 1]);
212#endif
213 *r++ = '\n';
214 } 207 }
215 } 208 }
216 *r++ = '\n'; 209 fmt_append(reply, reply_end, "\n");
217
218 return r - reply;
219} 210}
220 211
221static size_t stats_slash24s_txt(char *reply, size_t amount) { 212static void stats_slash24s_txt(char **reply, const char *reply_end, size_t amount) {
222 stats_network_node *slash24s_network_counters_root = NULL; 213 stats_network_node *slash24s_network_counters_root = NULL;
223 char *r = reply; 214 size_t i, bucket, peer_size = OT_PEER_SIZE4;
224 size_t i, bucket, peer_size = OT_PEER_SIZE4;
225 215
226 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 216 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
227 ot_vector *torrents_list = mutex_bucket_lock(bucket); 217 ot_vector *torrents_list = mutex_bucket_lock(bucket);
@@ -248,35 +238,28 @@ static size_t stats_slash24s_txt(char *reply, size_t amount) {
248 } 238 }
249 mutex_bucket_unlock(bucket, 0); 239 mutex_bucket_unlock(bucket, 0);
250 if (!g_opentracker_running) 240 if (!g_opentracker_running)
251 goto bailout_error; 241 goto done;
252 } 242 }
253 243
254 /* The tree is built. Now analyze */ 244 /* The tree is built. Now analyze */
255 r += stats_return_busy_networks(r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_MAXDEPTH); 245 stats_return_busy_networks(reply, reply_end, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_MAXDEPTH);
256 r += stats_return_busy_networks(r, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_LIMIT); 246 stats_return_busy_networks(reply, reply_end, slash24s_network_counters_root, amount, STATS_NETWORK_NODE_LIMIT);
257 goto success; 247 goto done;
258 248
259bailout_unlock: 249bailout_unlock:
260 mutex_bucket_unlock(bucket, 0); 250 mutex_bucket_unlock(bucket, 0);
261bailout_error: 251done:
262 r = reply;
263success:
264 stats_shift_down_network_count(&slash24s_network_counters_root, 0, sizeof(int) * 8 - 1); 252 stats_shift_down_network_count(&slash24s_network_counters_root, 0, sizeof(int) * 8 - 1);
265
266 return r - reply;
267} 253}
268 254
269#ifdef WANT_SPOT_WOODPECKER 255#ifdef WANT_SPOT_WOODPECKER
270static stats_network_node *stats_woodpeckers_tree; 256static stats_network_node *stats_woodpeckers_tree;
271static pthread_mutex_t g_woodpeckers_mutex = PTHREAD_MUTEX_INITIALIZER; 257static pthread_mutex_t g_woodpeckers_mutex = PTHREAD_MUTEX_INITIALIZER;
272 258
273static size_t stats_return_woodpeckers(char *reply, int amount) { 259static void stats_return_woodpeckers(char **reply, const char *reply_end, int amount) {
274 char *r = reply;
275
276 pthread_mutex_lock(&g_woodpeckers_mutex); 260 pthread_mutex_lock(&g_woodpeckers_mutex);
277 r += stats_return_busy_networks(r, stats_woodpeckers_tree, amount, STATS_NETWORK_NODE_MAXDEPTH); 261 stats_return_busy_networks(reply, reply_end, stats_woodpeckers_tree, amount, STATS_NETWORK_NODE_MAXDEPTH);
278 pthread_mutex_unlock(&g_woodpeckers_mutex); 262 pthread_mutex_unlock(&g_woodpeckers_mutex);
279 return r - reply;
280} 263}
281#endif 264#endif
282 265
@@ -316,10 +299,10 @@ static inline void stats_insert_into_highscore(size_t val, ot_record* list, size
316 299
317 300
318/* Fetches stats from tracker */ 301/* Fetches stats from tracker */
319size_t stats_top_txt(char *reply, size_t amount) { 302void stats_top_txt(char **reply, const char *reply_end, size_t amount) {
320 size_t j, idx, bucket; 303 size_t j, idx, bucket;
321 ot_record top100s[100], top100c[100], top100l[100]; 304 ot_record top100s[100], top100c[100], top100l[100];
322 char *r = reply, hex_out[42]; 305 char hex_out[42];
323 306
324 if (amount > 100) 307 if (amount > 100)
325 amount = 100; 308 amount = 100;
@@ -330,7 +313,7 @@ size_t stats_top_txt(char *reply, size_t amount) {
330 313
331 /* Iterate over complete torrent list */ 314 /* Iterate over complete torrent list */
332 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) { 315 for (bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket) {
333 ot_vector *torrents_list = mutex_bucket_lock(bucket); 316 ot_vector *torrents_list = mutex_bucket_lock(bucket);
334 for (j = 0; j < torrents_list->size; ++j) { 317 for (j = 0; j < torrents_list->size; ++j) {
335 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j; 318 ot_torrent *torrent = (ot_torrent *)(torrents_list->data) + j;
336 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count; 319 size_t peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count;
@@ -343,114 +326,110 @@ size_t stats_top_txt(char *reply, size_t amount) {
343 } 326 }
344 mutex_bucket_unlock(bucket, 0); 327 mutex_bucket_unlock(bucket, 0);
345 if (!g_opentracker_running) 328 if (!g_opentracker_running)
346 return 0; 329 return;
347 } 330 }
348 331
349 r += sprintf(r, "Top %zd torrents by peers:\n", amount); 332 fmt_append(reply, reply_end, "Top %zd torrents by peers:\n", amount);
350 for (idx = 0; idx < amount; ++idx) 333 for (idx = 0; idx < amount; ++idx)
351 if (top100c[idx].val) 334 if (top100c[idx].val)
352 r += sprintf(r, "\t%zd\t%s\n", top100c[idx].val, hex_fromhash(hex_out, top100c[idx].hash)); 335 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100c[idx].val, hex_from_hash(hex_out, top100c[idx].hash));
353 r += sprintf(r, "Top %zd torrents by seeds:\n", amount); 336 fmt_append(reply, reply_end, "Top %zd torrents by seeds:\n", amount);
354 for (idx = 0; idx < amount; ++idx) 337 for (idx = 0; idx < amount; ++idx)
355 if (top100s[idx].val) 338 if (top100s[idx].val)
356 r += sprintf(r, "\t%zd\t%s\n", top100s[idx].val, hex_fromhash(hex_out, top100s[idx].hash)); 339 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100s[idx].val, hex_from_hash(hex_out, top100s[idx].hash));
357 r += sprintf(r, "Top %zd torrents by leechers:\n", amount); 340 fmt_append(reply, reply_end, "Top %zd torrents by leechers:\n", amount);
358 for (idx = 0; idx < amount; ++idx) 341 for (idx = 0; idx < amount; ++idx)
359 if (top100l[idx].val) 342 if (top100l[idx].val)
360 r += sprintf(r, "\t%zd\t%s\n", top100l[idx].val, hex_fromhash(hex_out, top100l[idx].hash)); 343 fmt_append(reply, reply_end, "\t%zd\t%s\n", top100l[idx].val, hex_from_hash(hex_out, top100l[idx].hash));
361
362 return r - reply;
363} 344}
364 345
365static unsigned long events_per_time(unsigned long long events, time_t t) { return events / ((unsigned int)t ? (unsigned int)t : 1); } 346static unsigned long events_per_time(unsigned long long events, time_t t) { return events / ((unsigned int)t ? (unsigned int)t : 1); }
366 347
367static size_t stats_connections_mrtg(char *reply) { 348static void stats_connections_mrtg(char **reply, const char *reply_end) {
368 ot_time t = time(NULL) - ot_start_time; 349 ot_time t = time(NULL) - ot_start_time;
369 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", 350 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.",
370 ot_overall_tcp_connections + ot_overall_udp_connections, 351 ot_overall_tcp_connections + ot_overall_udp_connections,
371 ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), 352 ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600),
372 events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t), 353 events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
373 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 354 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
374} 355}
375 356
376static size_t stats_udpconnections_mrtg(char *reply) { 357static void stats_udpconnections_mrtg(char **reply, const char *reply_end) {
377 ot_time t = time(NULL) - ot_start_time; 358 ot_time t = time(NULL) - ot_start_time;
378 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_connections, 359 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats, %lu conns/s :: %lu success/s.", ot_overall_udp_connections,
379 ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), events_per_time(ot_overall_udp_connections, t), 360 ot_overall_udp_successfulannounces + ot_overall_udp_connects, (int)t, (int)(t / 3600), events_per_time(ot_overall_udp_connections, t),
380 events_per_time(ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 361 events_per_time(ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
381} 362}
382 363
383static size_t stats_tcpconnections_mrtg(char *reply) { 364static void stats_tcpconnections_mrtg(char **reply, const char *reply_end) {
384 time_t t = time(NULL) - ot_start_time; 365 time_t t = time(NULL) - ot_start_time;
385 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_connections, 366 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats, %lu conns/s :: %lu success/s.", ot_overall_tcp_connections,
386 ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections, t), 367 ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections, t),
387 events_per_time(ot_overall_tcp_successfulannounces, t)); 368 events_per_time(ot_overall_tcp_successfulannounces, t));
388} 369}
389 370
390static size_t stats_scrape_mrtg(char *reply) { 371static void stats_scrape_mrtg(char **reply, const char *reply_end) {
391 time_t t = time(NULL) - ot_start_time; 372 time_t t = time(NULL) - ot_start_time;
392 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)", ot_overall_tcp_successfulscrapes, 373 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker scrape stats, %lu scrape/s (tcp and udp)",
393 ot_overall_udp_successfulscrapes, (int)t, (int)(t / 3600), 374 ot_overall_tcp_successfulscrapes, ot_overall_udp_successfulscrapes, (int)t, (int)(t / 3600),
394 events_per_time((ot_overall_tcp_successfulscrapes + ot_overall_udp_successfulscrapes), t)); 375 events_per_time((ot_overall_tcp_successfulscrapes + ot_overall_udp_successfulscrapes), t));
395} 376}
396 377
397static size_t stats_fullscrapes_mrtg(char *reply) { 378static void stats_fullscrapes_mrtg(char **reply, const char *reply_end) {
398 ot_time t = time(NULL) - ot_start_time; 379 ot_time t = time(NULL) - ot_start_time;
399 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, 380 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats, %lu conns/s :: %lu bytes/s.",
400 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)); 381 ot_full_scrape_count * 1000, ot_full_scrape_size, (int)t, (int)(t / 3600), events_per_time(ot_full_scrape_count, t),
382 events_per_time(ot_full_scrape_size, t));
401} 383}
402 384
403static size_t stats_peers_mrtg(char *reply) { 385static void stats_peers_mrtg(char **reply, const char *reply_end) {
404 torrent_stats stats = {0, 0, 0}; 386 torrent_stats stats = {0, 0, 0};
405 387
406 iterate_all_torrents(torrent_statter, (uintptr_t)&stats); 388 iterate_all_torrents(torrent_statter, (uintptr_t)&stats);
407 389
408 return sprintf(reply, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", stats.peer_count, stats.seed_count, stats.torrent_count); 390 fmt_append(reply, reply_end, "%llu\n%llu\nopentracker serving %llu torrents\nopentracker", stats.peer_count, stats.seed_count,
391 stats.torrent_count);
409} 392}
410 393
411static size_t stats_torrents_mrtg(char *reply) { 394static void stats_torrents_mrtg(char **reply, const char *reply_end) {
412 size_t torrent_count = mutex_get_torrent_count(); 395 size_t torrent_count = mutex_get_torrent_count();
413 396
414 return sprintf(reply, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", torrent_count, (size_t)0, torrent_count); 397 fmt_append(reply, reply_end, "%zd\n%zd\nopentracker serving %zd torrents\nopentracker", torrent_count, (size_t)0, torrent_count);
415} 398}
416 399
417static size_t stats_httperrors_txt(char *reply) { 400static void stats_httperrors_txt(char **reply, const char *reply_end) {
418 return sprintf(reply, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n", ot_failed_request_counts[0], 401 fmt_append(reply, reply_end, "302 RED %llu\n400 ... %llu\n400 PAR %llu\n400 COM %llu\n403 IP %llu\n404 INV %llu\n500 SRV %llu\n",
419 ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[3], ot_failed_request_counts[4], 402 ot_failed_request_counts[0], ot_failed_request_counts[1], ot_failed_request_counts[2], ot_failed_request_counts[3],
420 ot_failed_request_counts[5], ot_failed_request_counts[6]); 403 ot_failed_request_counts[4], ot_failed_request_counts[5], ot_failed_request_counts[6]);
421} 404}
422 405
423static size_t stats_return_renew_bucket(char *reply) { 406static void stats_return_renew_bucket(char **reply, const char *reply_end) {
424 char *r = reply; 407 int i;
425 int i;
426 408
427 for (i = 0; i < OT_PEER_TIMEOUT; ++i) 409 for (i = 0; i < OT_PEER_TIMEOUT; ++i)
428 r += sprintf(r, "%02i %llu\n", i, ot_renewed[i]); 410 fmt_append(reply, reply_end, "%02i %llu\n", i, ot_renewed[i]);
429 return r - reply;
430} 411}
431 412
432static size_t stats_return_sync_mrtg(char *reply) { 413static void stats_return_sync_mrtg(char **reply, const char *reply_end) {
433 ot_time t = time(NULL) - ot_start_time; 414 ot_time t = time(NULL) - ot_start_time;
434 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", ot_overall_sync_count, 0LL, (int)t, 415 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker connections, %lu conns/s :: %lu success/s.", ot_overall_sync_count, 0LL,
435 (int)(t / 3600), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t), 416 (int)t, (int)(t / 3600), events_per_time(ot_overall_tcp_connections + ot_overall_udp_connections, t),
436 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t)); 417 events_per_time(ot_overall_tcp_successfulannounces + ot_overall_udp_successfulannounces + ot_overall_udp_connects, t));
437} 418}
438 419
439static size_t stats_return_completed_mrtg(char *reply) { 420static void stats_return_completed_mrtg(char **reply, const char *reply_end) {
440 ot_time t = time(NULL) - ot_start_time; 421 ot_time t = time(NULL) - ot_start_time;
441 422
442 return sprintf(reply, "%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", ot_overall_completed, 0LL, (int)t, (int)(t / 3600), 423 fmt_append(reply, reply_end, "%llu\n%llu\n%i seconds (%i hours)\nopentracker, %lu completed/h.", ot_overall_completed, 0LL, (int)t, (int)(t / 3600),
443 events_per_time(ot_overall_completed, t / 3600)); 424 events_per_time(ot_overall_completed, t / 3600));
444} 425}
445 426
446#ifdef WANT_LOG_NUMWANT 427#ifdef WANT_LOG_NUMWANT
447extern unsigned long long numwants[201]; 428extern unsigned long long numwants[201];
448static size_t stats_return_numwants(char *reply) { 429static void stats_return_numwants(char **reply, const char *reply_end) {
449 char *r = reply; 430 int i;
450 int i;
451 for (i = 0; i <= 200; ++i) 431 for (i = 0; i <= 200; ++i)
452 r += sprintf(r, "%03d => %lld\n", i, numwants[i]); 432 fmt_append(reply, reply_end, "%03d => %lld\n", i, numwants[i]);
453 return r - reply;
454} 433}
455#endif 434#endif
456 435
@@ -463,148 +442,158 @@ static void stats_return_fulllog(size_t *iovec_entries, struct iovec **iovector,
463 442
464 while (loglist) { 443 while (loglist) {
465 if (r + (loglist->size + 64) >= re) { 444 if (r + (loglist->size + 64) >= re) {
466 r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE); 445 r = iovec_next_chunk(iovec_entries, iovector, r, 32 * OT_STATS_TMPSIZE);
467 if (!r) 446 if (!r)
468 return; 447 return;
469 re = r + 32 * OT_STATS_TMPSIZE; 448 re = r + 32 * OT_STATS_TMPSIZE;
470 } 449 }
471 r += sprintf(r, "%08ld: ", loglist->time); 450 char ip_readable[64];
472 r += ip_format(r, loglist->ip);
473 *r++ = '\n';
474 memcpy(r, loglist->data, loglist->size);
475 r += loglist->size;
476 *r++ = '\n';
477 *r++ = '*';
478 *r++ = '\n';
479 *r++ = '\n';
480 451
481 llnext = loglist->next; 452 ip_readable[ip_format(ip_readable, loglist->ip)] = 0;
453 fmt_append(&r, re, "%08ld: %s\n", loglist->time, ip_readable);
454 fmt_bytes(&r, re, loglist->data, loglist->size);
455 fmt_append(&r, re, "\n*\n\n");
456
457 llnext = loglist->next;
482 free(loglist->data); 458 free(loglist->data);
483 free(loglist); 459 free(loglist);
484 loglist = llnext; 460 loglist = llnext;
485 } 461 }
486 iovec_fixlast(iovec_entries, iovector, r); 462 iovec_trim_last(iovec_entries, iovector, r);
487} 463}
488#endif 464#endif
489 465
490static size_t stats_return_everything(char *reply) { 466static void stats_return_everything(char **reply, const char *reply_end) {
491 torrent_stats stats = {0, 0, 0}; 467 torrent_stats stats = {0, 0, 0};
492 int i; 468 int i;
493 char *r = reply;
494 469
495 iterate_all_torrents(torrent_statter, (uintptr_t)&stats); 470 iterate_all_torrents(torrent_statter, (uintptr_t)&stats);
496 471
497 r += sprintf(r, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 472 fmt_append(reply, reply_end, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
498 r += sprintf(r, "<stats>\n"); 473 fmt_append(reply, reply_end, "<stats>\n");
499 r += sprintf(r, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id); 474 fmt_append(reply, reply_end, " <tracker_id>%" PRIu32 "</tracker_id>\n", g_tracker_id);
500 r += sprintf(r, " <version>\n"); 475 fmt_append(reply, reply_end, " <version>\n");
501 r += stats_return_tracker_version(r); 476 stats_return_tracker_version(reply, reply_end);
502 r += sprintf(r, " </version>\n"); 477 fmt_append(reply, reply_end, " </version>\n");
503 r += sprintf(r, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time)); 478 fmt_append(reply, reply_end, " <uptime>%llu</uptime>\n", (unsigned long long)(time(NULL) - ot_start_time));
504 r += sprintf(r, " <torrents>\n"); 479 fmt_append(reply, reply_end, " <torrents>\n");
505 r += sprintf(r, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count()); 480 fmt_append(reply, reply_end, " <count_mutex>%zd</count_mutex>\n", mutex_get_torrent_count());
506 r += sprintf(r, " <count_iterator>%llu</count_iterator>\n", stats.torrent_count); 481 fmt_append(reply, reply_end, " <count_iterator>%llu</count_iterator>\n", stats.torrent_count);
507 r += sprintf(r, " </torrents>\n"); 482 fmt_append(reply, reply_end, " </torrents>\n");
508 r += sprintf(r, " <peers>\n <count>%llu</count>\n </peers>\n", stats.peer_count); 483 fmt_append(reply, reply_end, " <peers>\n <count>%llu</count>\n </peers>\n", stats.peer_count);
509 r += sprintf(r, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count); 484 fmt_append(reply, reply_end, " <seeds>\n <count>%llu</count>\n </seeds>\n", stats.seed_count);
510 r += sprintf(r, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed); 485 fmt_append(reply, reply_end, " <completed>\n <count>%llu</count>\n </completed>\n", ot_overall_completed);
511 r += sprintf(r, " <connections>\n"); 486 fmt_append(reply, reply_end, " <connections>\n");
512 r += sprintf(r, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n", 487 fmt_append(reply, reply_end, " <tcp>\n <accept>%llu</accept>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n </tcp>\n",
513 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes); 488 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, ot_overall_tcp_successfulscrapes);
514 r += sprintf(r, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n", 489 fmt_append(reply, reply_end, " <udp>\n <overall>%llu</overall>\n <connect>%llu</connect>\n <announce>%llu</announce>\n <scrape>%llu</scrape>\n <missmatch>%llu</missmatch>\n </udp>\n",
515 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes, 490 ot_overall_udp_connections, ot_overall_udp_connects, ot_overall_udp_successfulannounces, ot_overall_udp_successfulscrapes,
516 ot_overall_udp_connectionidmissmatches); 491 ot_overall_udp_connectionidmissmatches);
517 r += sprintf(r, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count); 492 fmt_append(reply, reply_end, " <livesync>\n <count>%llu</count>\n </livesync>\n", ot_overall_sync_count);
518 r += sprintf(r, " </connections>\n"); 493 fmt_append(reply, reply_end, " </connections>\n");
519 r += sprintf(r, " <debug>\n"); 494 fmt_append(reply, reply_end, " <debug>\n");
520 r += sprintf(r, " <renew>\n"); 495 fmt_append(reply, reply_end, " <renew>\n");
521 for (i = 0; i < OT_PEER_TIMEOUT; ++i) 496 for (i = 0; i < OT_PEER_TIMEOUT; ++i)
522 r += sprintf(r, " <count interval=\"%02i\">%llu</count>\n", i, ot_renewed[i]); 497 fmt_append(reply, reply_end, " <count interval=\"%02i\">%llu</count>\n", i, ot_renewed[i]);
523 r += sprintf(r, " </renew>\n"); 498 fmt_append(reply, reply_end, " </renew>\n");
524 r += sprintf(r, " <http_error>\n"); 499 fmt_append(reply, reply_end, " <http_error>\n");
525 for (i = 0; i < CODE_HTTPERROR_COUNT; ++i) 500 for (i = 0; i < CODE_HTTPERROR_COUNT; ++i)
526 r += sprintf(r, " <count code=\"%s\">%llu</count>\n", ot_failed_request_names[i], ot_failed_request_counts[i]); 501 fmt_append(reply, reply_end, " <count code=\"%s\">%llu</count>\n", ot_failed_request_names[i], ot_failed_request_counts[i]);
527 r += sprintf(r, " </http_error>\n"); 502 fmt_append(reply, reply_end, " </http_error>\n");
528 r += sprintf(r, " <mutex_stall>\n <count>%llu</count>\n </mutex_stall>\n", ot_overall_stall_count); 503 fmt_append(reply, reply_end, " <mutex_stall>\n <count>%llu</count>\n </mutex_stall>\n", ot_overall_stall_count);
529 r += sprintf(r, " </debug>\n"); 504 fmt_append(reply, reply_end, " </debug>\n");
530 r += sprintf(r, "</stats>"); 505 fmt_append(reply, reply_end, "</stats>");
531 return r - reply;
532} 506}
533 507
534size_t stats_return_tracker_version(char *reply) { 508void stats_return_tracker_version(char **reply, const char *reply_end) {
535#define QUOTE(name) #name 509#define QUOTE(name) #name
536#define SQUOTE(name) QUOTE(name) 510#define SQUOTE(name) QUOTE(name)
537 return sprintf(reply, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n"); 511 fmt_append(reply, reply_end, "https://erdgeist.org/gitweb/opentracker/commit/?id=" SQUOTE(GIT_VERSION) "\n");
538} 512}
539 513
540size_t return_stats_for_tracker(char *reply, int mode, int format) { 514void return_stats_for_tracker(char **reply, const char *reply_end, int mode, int format) {
541 (void)format; 515 (void)format;
542 switch (mode & TASK_TASK_MASK) { 516 switch (mode & TASK_TASK_MASK) {
543 case TASK_STATS_CONNS: 517 case TASK_STATS_CONNS:
544 return stats_connections_mrtg(reply); 518 stats_connections_mrtg(reply, reply_end);
519 break;
545 case TASK_STATS_SCRAPE: 520 case TASK_STATS_SCRAPE:
546 return stats_scrape_mrtg(reply); 521 stats_scrape_mrtg(reply, reply_end);
522 break;
547 case TASK_STATS_UDP: 523 case TASK_STATS_UDP:
548 return stats_udpconnections_mrtg(reply); 524 stats_udpconnections_mrtg(reply, reply_end);
525 break;
549 case TASK_STATS_TCP: 526 case TASK_STATS_TCP:
550 return stats_tcpconnections_mrtg(reply); 527 stats_tcpconnections_mrtg(reply, reply_end);
528 break;
551 case TASK_STATS_FULLSCRAPE: 529 case TASK_STATS_FULLSCRAPE:
552 return stats_fullscrapes_mrtg(reply); 530 stats_fullscrapes_mrtg(reply, reply_end);
531 break;
553 case TASK_STATS_COMPLETED: 532 case TASK_STATS_COMPLETED:
554 return stats_return_completed_mrtg(reply); 533 stats_return_completed_mrtg(reply, reply_end);
534 break;
555 case TASK_STATS_HTTPERRORS: 535 case TASK_STATS_HTTPERRORS:
556 return stats_httperrors_txt(reply); 536 stats_httperrors_txt(reply, reply_end);
537 break;
557 case TASK_STATS_VERSION: 538 case TASK_STATS_VERSION:
558 return stats_return_tracker_version(reply); 539 stats_return_tracker_version(reply, reply_end);
540 break;
559 case TASK_STATS_RENEW: 541 case TASK_STATS_RENEW:
560 return stats_return_renew_bucket(reply); 542 stats_return_renew_bucket(reply, reply_end);
543 break;
561 case TASK_STATS_SYNCS: 544 case TASK_STATS_SYNCS:
562 return stats_return_sync_mrtg(reply); 545 stats_return_sync_mrtg(reply, reply_end);
546 break;
563#ifdef WANT_LOG_NUMWANT 547#ifdef WANT_LOG_NUMWANT
564 case TASK_STATS_NUMWANTS: 548 case TASK_STATS_NUMWANTS:
565 return stats_return_numwants(reply); 549 stats_return_numwants(reply, reply_end);
550 break;
566#endif 551#endif
567 default: 552 default:
568 return 0; 553 break;
569 } 554 }
570} 555}
571 556
572static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) { 557static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_tasktype mode) {
573 char *r; 558 char *r;
559 const char *r_end;
574 560
575 *iovec_entries = 0; 561 *iovec_entries = 0;
576 *iovector = NULL; 562 *iovector = NULL;
577 if (!(r = iovec_increase(iovec_entries, iovector, OT_STATS_TMPSIZE))) 563 if (!(r = iovec_new_chunk(iovec_entries, iovector, OT_STATS_TMPSIZE)))
578 return; 564 return;
565 r_end = r + OT_STATS_TMPSIZE;
579 566
580 switch (mode & TASK_TASK_MASK) { 567 switch (mode & TASK_TASK_MASK) {
581 case TASK_STATS_TORRENTS: 568 case TASK_STATS_TORRENTS:
582 r += stats_torrents_mrtg(r); 569 stats_torrents_mrtg(&r, r_end);
583 break; 570 break;
584 case TASK_STATS_PEERS: 571 case TASK_STATS_PEERS:
585 r += stats_peers_mrtg(r); 572 stats_peers_mrtg(&r, r_end);
586 break; 573 break;
587 case TASK_STATS_SLASH24S: 574 case TASK_STATS_SLASH24S:
588 r += stats_slash24s_txt(r, 128); 575 stats_slash24s_txt(&r, r_end, 128);
589 break; 576 break;
590 case TASK_STATS_TOP10: 577 case TASK_STATS_TOP10:
591 r += stats_top_txt(r, 10); 578 stats_top_txt(&r, r_end, 10);
592 break; 579 break;
593 case TASK_STATS_TOP100: 580 case TASK_STATS_TOP100:
594 r = iovec_fix_increase_or_free(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE); 581 r = iovec_next_chunk(iovec_entries, iovector, r, 4 * OT_STATS_TMPSIZE);
595 if (!r) 582 if (!r)
596 return; 583 return;
597 r += stats_top_txt(r, 100); 584 r_end = r + 4 * OT_STATS_TMPSIZE;
585 stats_top_txt(&r, r_end, 100);
598 break; 586 break;
599 case TASK_STATS_EVERYTHING: 587 case TASK_STATS_EVERYTHING:
600 r = iovec_fix_increase_or_free(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT); 588 r = iovec_next_chunk(iovec_entries, iovector, r, OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT);
601 if (!r) 589 if (!r)
602 return; 590 return;
603 r += stats_return_everything(r); 591 r_end = r + OT_STATS_TMPSIZE + 64 * OT_PEER_TIMEOUT;
592 stats_return_everything(&r, r_end);
604 break; 593 break;
605#ifdef WANT_SPOT_WOODPECKER 594#ifdef WANT_SPOT_WOODPECKER
606 case TASK_STATS_WOODPECKERS: 595 case TASK_STATS_WOODPECKERS:
607 r += stats_return_woodpeckers(r, 128); 596 stats_return_woodpeckers(&r, r_end, 128);
608 break; 597 break;
609#endif 598#endif
610#ifdef WANT_FULLLOG_NETWORKS 599#ifdef WANT_FULLLOG_NETWORKS
@@ -616,7 +605,7 @@ static void stats_make(size_t *iovec_entries, struct iovec **iovector, ot_taskty
616 iovec_free(iovec_entries, iovector); 605 iovec_free(iovec_entries, iovector);
617 return; 606 return;
618 } 607 }
619 iovec_fixlast(iovec_entries, iovector, r); 608 iovec_trim_last(iovec_entries, iovector, r);
620} 609}
621 610
622void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_data) { 611void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_data) {
@@ -655,18 +644,14 @@ void stats_issue_event(ot_status_event event, PROTO_FLAG proto, uintptr_t event_
655 localtime_r(&ttt, &time_now); 644 localtime_r(&ttt, &time_now);
656 strftime(timestring, sizeof(timestring), "%FT%T%z", &time_now); 645 strftime(timestring, sizeof(timestring), "%FT%T%z", &time_now);
657 646
658 hex_fromhash(hash_hex, *ws->hash); 647 hex_from_hash(hash_hex, *ws->hash);
659 if (ws->peer_id) 648 if (ws->peer_id)
660 hex_fromhash(peerid_hex, (uint8_t *)ws->peer_id); 649 hex_from_hash(peerid_hex, (uint8_t *)ws->peer_id);
661 else { 650 else {
662 *peerid_hex = 0; 651 *peerid_hex = 0;
663 } 652 }
664 653
665 ip_readable[ip_format(ip_readable, (char *)&ws->peer)] = 0; 654 ip_readable[ip_format(ip_readable, (char *)&ws->peer)] = 0;
666#if 0
667 /* XXX */
668 ip_readable[ fmt_ip4( ip_readable, (char*)&ws->peer ) ] = 0;
669#endif
670 syslog(LOG_INFO, "time=%s event=completed info_hash=%s peer_id=%s ip=%s", timestring, hash_hex, peerid_hex, ip_readable); 655 syslog(LOG_INFO, "time=%s event=completed info_hash=%s peer_id=%s ip=%s", timestring, hash_hex, peerid_hex, ip_readable);
671 } 656 }
672#endif 657#endif