diff options
-rw-r--r-- | opentracker.c | 47 | ||||
-rw-r--r-- | ot_fullscrape.c | 51 |
2 files changed, 76 insertions, 22 deletions
diff --git a/opentracker.c b/opentracker.c index 06be4fa..59b561b 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -284,6 +284,7 @@ static void httpresponse( const int64 s, char *data _DEBUG_HTTPERROR_PARAM( size | |||
284 | ot_torrent *torrent; | 284 | ot_torrent *torrent; |
285 | ot_hash *hash = NULL; | 285 | ot_hash *hash = NULL; |
286 | int numwant, tmp, scanon, mode; | 286 | int numwant, tmp, scanon, mode; |
287 | ot_tasktype format = TASK_FULLSCRAPE; | ||
287 | unsigned short port = htons(6881); | 288 | unsigned short port = htons(6881); |
288 | ssize_t len; | 289 | ssize_t len; |
289 | size_t reply_size = 0, reply_off; | 290 | size_t reply_size = 0, reply_off; |
@@ -359,7 +360,7 @@ LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | |||
359 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; | 360 | if( !byte_diff( data, 2, "sc" ) ) goto SCRAPE_WORKAROUND; |
360 | if( byte_diff(data,5,"stats")) HTTPERROR_404; | 361 | if( byte_diff(data,5,"stats")) HTTPERROR_404; |
361 | scanon = 1; | 362 | scanon = 1; |
362 | mode = STATS_PEERS; | 363 | mode = TASK_STATS_PEERS; |
363 | 364 | ||
364 | while( scanon ) { | 365 | while( scanon ) { |
365 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { | 366 | switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) { |
@@ -373,24 +374,52 @@ LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] ); | |||
373 | } | 374 | } |
374 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 4 ) HTTPERROR_400_PARAM; | 375 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 4 ) HTTPERROR_400_PARAM; |
375 | if( !byte_diff(data,4,"peer")) | 376 | if( !byte_diff(data,4,"peer")) |
376 | mode = STATS_PEERS; | 377 | mode = TASK_STATS_PEERS; |
377 | else if( !byte_diff(data,4,"conn")) | 378 | else if( !byte_diff(data,4,"conn")) |
378 | mode = STATS_CONNS; | 379 | mode = TASK_STATS_CONNS; |
379 | else if( !byte_diff(data,4,"top5")) | 380 | else if( !byte_diff(data,4,"top5")) |
380 | mode = STATS_TOP5; | 381 | mode = TASK_STATS_TOP5; |
381 | else if( !byte_diff(data,4,"fscr")) | 382 | else if( !byte_diff(data,4,"fscr")) |
382 | mode = STATS_FULLSCRAPE; | 383 | mode = TASK_STATS_FULLSCRAPE; |
383 | else if( !byte_diff(data,4,"tcp4")) | 384 | else if( !byte_diff(data,4,"tcp4")) |
384 | mode = STATS_TCP; | 385 | mode = TASK_STATS_TCP; |
385 | else if( !byte_diff(data,4,"udp4")) | 386 | else if( !byte_diff(data,4,"udp4")) |
386 | mode = STATS_UDP; | 387 | mode = TASK_STATS_UDP; |
387 | else if( !byte_diff(data,4,"s24s")) | 388 | else if( !byte_diff(data,4,"s24s")) |
388 | mode = STATS_SLASH24S; | 389 | mode = TASK_STATS_SLASH24S; |
390 | else if( !byte_diff(data,4,"tpbs")) | ||
391 | mode = TASK_STATS_TPB; | ||
389 | else | 392 | else |
390 | HTTPERROR_400_PARAM; | 393 | HTTPERROR_400_PARAM; |
394 | break; | ||
395 | case 6: | ||
396 | if( byte_diff(data,6,"format")) { | ||
397 | scan_urlencoded_skipvalue( &c ); | ||
398 | continue; | ||
399 | } | ||
400 | if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 3 ) HTTPERROR_400_PARAM; | ||
401 | if( !byte_diff(data,3,"bin")) | ||
402 | format = TASK_FULLSCRAPE_TPB_BINARY; | ||
403 | else if( !byte_diff(data,3,"ben")) | ||
404 | format = TASK_FULLSCRAPE; | ||
405 | else if( !byte_diff(data,3,"url")) | ||
406 | format = TASK_FULLSCRAPE_TPB_URLENCODED; | ||
407 | else if( !byte_diff(data,3,"txt")) | ||
408 | format = TASK_FULLSCRAPE_TPB_ASCII; | ||
409 | else | ||
410 | HTTPERROR_400_PARAM; | ||
411 | break; | ||
391 | } | 412 | } |
392 | } | 413 | } |
393 | 414 | ||
415 | if( mode == TASK_STATS_TPB ) { | ||
416 | /* Pass this task to the worker thread */ | ||
417 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
418 | fullscrape_deliver( s, format ); | ||
419 | io_dontwantread( s ); | ||
420 | return; | ||
421 | } | ||
422 | |||
394 | // default format for now | 423 | // default format for now |
395 | if( !( reply_size = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500; | 424 | if( !( reply_size = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500; |
396 | break; | 425 | break; |
@@ -410,7 +439,7 @@ write( 2, debug_request, l ); | |||
410 | #endif | 439 | #endif |
411 | /* Pass this task to the worker thread */ | 440 | /* Pass this task to the worker thread */ |
412 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | 441 | h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; |
413 | fullscrape_deliver( s ); | 442 | fullscrape_deliver( s, TASK_FULLSCRAPE ); |
414 | io_dontwantread( s ); | 443 | io_dontwantread( s ); |
415 | return; | 444 | return; |
416 | } | 445 | } |
diff --git a/ot_fullscrape.c b/ot_fullscrape.c index 58e525f..25d6bd5 100644 --- a/ot_fullscrape.c +++ b/ot_fullscrape.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <pthread.h> | 8 | #include <pthread.h> |
9 | 9 | ||
10 | /* Libowfat */ | 10 | /* Libowfat */ |
11 | #include "textcode.h" | ||
11 | 12 | ||
12 | /* Opentracker */ | 13 | /* Opentracker */ |
13 | #include "trackerlogic.h" | 14 | #include "trackerlogic.h" |
@@ -25,7 +26,11 @@ | |||
25 | #define OT_FULLSCRAPE_MAXENTRYLEN 100 | 26 | #define OT_FULLSCRAPE_MAXENTRYLEN 100 |
26 | 27 | ||
27 | /* Forward declaration */ | 28 | /* Forward declaration */ |
28 | static void fullscrape_make( int *iovec_entries, struct iovec **iovector ); | 29 | static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ); |
30 | |||
31 | /* Converter function from memory to human readable hex strings | ||
32 | XXX - Duplicated from ot_stats. Needs fix. */ | ||
33 | static char*to_hex(char*d,ot_byte*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;} | ||
29 | 34 | ||
30 | /* This is the entry point into this worker thread | 35 | /* This is the entry point into this worker thread |
31 | It grabs tasks from mutex_tasklist and delivers results back | 36 | It grabs tasks from mutex_tasklist and delivers results back |
@@ -37,8 +42,9 @@ static void * fullscrape_worker( void * args) { | |||
37 | args = args; | 42 | args = args; |
38 | 43 | ||
39 | while( 1 ) { | 44 | while( 1 ) { |
40 | ot_taskid taskid = mutex_workqueue_poptask( OT_TASKTYPE_FULLSCRAPE ); | 45 | ot_tasktype tasktype = TASK_FULLSCRAPE; |
41 | fullscrape_make( &iovec_entries, &iovector ); | 46 | ot_taskid taskid = mutex_workqueue_poptask( &tasktype ); |
47 | fullscrape_make( &iovec_entries, &iovector, tasktype ); | ||
42 | if( mutex_workqueue_pushresult( taskid, iovec_entries, iovector ) ) | 48 | if( mutex_workqueue_pushresult( taskid, iovec_entries, iovector ) ) |
43 | iovec_free( &iovec_entries, &iovector ); | 49 | iovec_free( &iovec_entries, &iovector ); |
44 | } | 50 | } |
@@ -50,11 +56,11 @@ void fullscrape_init( ) { | |||
50 | pthread_create( &thread_id, NULL, fullscrape_worker, NULL ); | 56 | pthread_create( &thread_id, NULL, fullscrape_worker, NULL ); |
51 | } | 57 | } |
52 | 58 | ||
53 | void fullscrape_deliver( int64 socket ) { | 59 | void fullscrape_deliver( int64 socket, ot_tasktype tasktype ) { |
54 | mutex_workqueue_pushtask( socket, OT_TASKTYPE_FULLSCRAPE ); | 60 | mutex_workqueue_pushtask( socket, tasktype ); |
55 | } | 61 | } |
56 | 62 | ||
57 | static void fullscrape_make( int *iovec_entries, struct iovec **iovector ) { | 63 | static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) { |
58 | int bucket; | 64 | int bucket; |
59 | char *r, *re; | 65 | char *r, *re; |
60 | 66 | ||
@@ -68,8 +74,11 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector ) { | |||
68 | This works as a low watermark */ | 74 | This works as a low watermark */ |
69 | re = r + OT_SCRAPE_CHUNK_SIZE; | 75 | re = r + OT_SCRAPE_CHUNK_SIZE; |
70 | 76 | ||
71 | /* Start reply dictionary */ | 77 | /* Reply dictionary only needed for bencoded fullscrape */ |
72 | memmove( r, "d5:filesd", 9 ); r += 9; | 78 | if( mode == TASK_FULLSCRAPE ) { |
79 | memmove( r, "d5:filesd", 9 ); | ||
80 | r += 9; | ||
81 | } | ||
73 | 82 | ||
74 | /* For each bucket... */ | 83 | /* For each bucket... */ |
75 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { | 84 | for( bucket=0; bucket<OT_BUCKET_COUNT; ++bucket ) { |
@@ -83,15 +92,29 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector ) { | |||
83 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[tor_offset] ).peer_list; | 92 | ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[tor_offset] ).peer_list; |
84 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[tor_offset] ).hash; | 93 | ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[tor_offset] ).hash; |
85 | 94 | ||
86 | /* If torrent has peers or download count, its interesting */ | 95 | switch( mode ) { |
87 | if( peer_list->peer_count || peer_list->down_count ) { | 96 | case TASK_FULLSCRAPE: |
88 | 97 | default: | |
89 | /* push hash as bencoded string */ | 98 | /* push hash as bencoded string */ |
90 | *r++='2'; *r++='0'; *r++=':'; | 99 | *r++='2'; *r++='0'; *r++=':'; |
91 | memmove( r, hash, 20 ); r+=20; | 100 | memmove( r, hash, 20 ); r+=20; |
92 | 101 | ||
93 | /* push rest of the scrape string */ | 102 | /* push rest of the scrape string */ |
94 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count ); | 103 | r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zdee", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count ); |
104 | break; | ||
105 | case TASK_FULLSCRAPE_TPB_ASCII: | ||
106 | to_hex( r, *hash ); r+=40; | ||
107 | r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count ); | ||
108 | break; | ||
109 | case TASK_FULLSCRAPE_TPB_BINARY: | ||
110 | memmove( r, hash, 20 ); r+=20; | ||
111 | *(ot_dword*)r++ = htonl( (uint32_t)peer_list->seed_count ); | ||
112 | *(ot_dword*)r++ = htonl( (uint32_t)( peer_list->peer_count-peer_list->seed_count) ); | ||
113 | break; | ||
114 | case TASK_FULLSCRAPE_TPB_URLENCODED: | ||
115 | r += fmt_urlencoded( r, (char *)*hash, 20 ); | ||
116 | r += sprintf( r, ":%zd:%zd\n", peer_list->seed_count, peer_list->peer_count-peer_list->seed_count ); | ||
117 | break; | ||
95 | } | 118 | } |
96 | 119 | ||
97 | /* If we reached our low watermark in buffer... */ | 120 | /* If we reached our low watermark in buffer... */ |
@@ -120,8 +143,10 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector ) { | |||
120 | mutex_bucket_unlock( bucket ); | 143 | mutex_bucket_unlock( bucket ); |
121 | } | 144 | } |
122 | 145 | ||
123 | /* Close bencoded scrape dictionary */ | 146 | /* Close bencoded scrape dictionary if necessary */ |
124 | *r++='e'; *r++='e'; | 147 | if( mode == TASK_FULLSCRAPE ) { |
148 | *r++='e'; *r++='e'; | ||
149 | } | ||
125 | 150 | ||
126 | /* Release unused memory in current output buffer */ | 151 | /* Release unused memory in current output buffer */ |
127 | iovec_fixlast( iovec_entries, iovector, OT_SCRAPE_CHUNK_SIZE - ( re - r ) ); | 152 | iovec_fixlast( iovec_entries, iovector, OT_SCRAPE_CHUNK_SIZE - ( re - r ) ); |