summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opentracker.c59
-rw-r--r--ot_fullscrape.c70
2 files changed, 104 insertions, 25 deletions
diff --git a/opentracker.c b/opentracker.c
index a2ada33..57c7e9a 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -43,6 +43,7 @@
43 43
44/* Globals */ 44/* Globals */
45static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80; 45static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80;
46static const size_t SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING = 32;
46static const size_t SUCCESS_HTTP_SIZE_OFF = 17; 47static const size_t SUCCESS_HTTP_SIZE_OFF = 17;
47static uint32_t g_adminip_addresses[OT_ADMINIP_MAX]; 48static uint32_t g_adminip_addresses[OT_ADMINIP_MAX];
48static unsigned int g_adminip_count = 0; 49static unsigned int g_adminip_count = 0;
@@ -73,15 +74,14 @@ static size_t ot_sockets_count = 0;
73 74
74#ifdef _DEBUG_HTTPERROR 75#ifdef _DEBUG_HTTPERROR
75static char debug_request[8192]; 76static char debug_request[8192];
76#define _DEBUG_HTTPERROR_PARAM( param ) , param
77#else
78#define _DEBUG_HTTPERROR_PARAM( param )
79#endif 77#endif
80 78
81typedef enum { 79typedef enum {
82 STRUCT_HTTP_FLAG_ARRAY_USED = 1, 80 STRUCT_HTTP_FLAG_ARRAY_USED = 1,
83 STRUCT_HTTP_FLAG_IOB_USED = 2, 81 STRUCT_HTTP_FLAG_IOB_USED = 2,
84 STRUCT_HTTP_FLAG_WAITINGFORTASK = 4 82 STRUCT_HTTP_FLAG_WAITINGFORTASK = 4,
83 STRUCT_HTTP_FLAG_GZIP = 8,
84 STRUCT_HTTP_FLAG_BZIP2 = 16
85} STRUCT_HTTP_FLAG; 85} STRUCT_HTTP_FLAG;
86 86
87struct http_data { 87struct http_data {
@@ -100,7 +100,7 @@ static int ot_ip_compare( const void *a, const void *b ) { return memcmp( a,b,4
100int main( int argc, char **argv ); 100int main( int argc, char **argv );
101 101
102static void httperror( const int64 s, const char *title, const char *message ); 102static void httperror( const int64 s, const char *title, const char *message );
103static void httpresponse( const int64 s, char *data _DEBUG_HTTPERROR_PARAM(size_t l ) ); 103static void httpresponse( const int64 s, char *data, size_t l );
104 104
105static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector ); 105static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovector );
106static void senddata( const int64 s, char *buffer, const size_t size ); 106static void senddata( const int64 s, char *buffer, const size_t size );
@@ -162,7 +162,7 @@ static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovec
162 iovec_free( &iovec_entries, &iovector ); 162 iovec_free( &iovec_entries, &iovector );
163 HTTPERROR_500; 163 HTTPERROR_500;
164 } 164 }
165 165
166 /* If this socket collected request in a buffer, 166 /* If this socket collected request in a buffer,
167 free it now */ 167 free it now */
168 if( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) { 168 if( h->flag & STRUCT_HTTP_FLAG_ARRAY_USED ) {
@@ -173,20 +173,24 @@ static void sendiovecdata( const int64 s, int iovec_entries, struct iovec *iovec
173 /* If we came here, wait for the answer is over */ 173 /* If we came here, wait for the answer is over */
174 h->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 174 h->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
175 175
176 /* Our answers never are 0 bytes. Return an error. */ 176 /* Our answers never are 0 vectors. Return an error. */
177 if( !iovec_entries || !iovector[0].iov_len ) { 177 if( !iovec_entries ) {
178 iovec_free( &iovec_entries, &iovector );
179 HTTPERROR_500; 178 HTTPERROR_500;
180 } 179 }
181 180
182 /* Prepare space for http header */ 181 /* Prepare space for http header */
183 header = malloc( SUCCESS_HTTP_HEADER_LENGTH ); 182 header = malloc( SUCCESS_HTTP_HEADER_LENGTH + SUCCESS_HTTP_HEADER_LENGHT_CONTENT_ENCODING );
184 if( !header ) { 183 if( !header ) {
185 iovec_free( &iovec_entries, &iovector ); 184 iovec_free( &iovec_entries, &iovector );
186 HTTPERROR_500; 185 HTTPERROR_500;
187 } 186 }
188 187
189 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size ); 188 if( h->flag & STRUCT_HTTP_FLAG_GZIP )
189 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: gzip\r\nContent-Length: %zd\r\n\r\n", size );
190 else if( h->flag & STRUCT_HTTP_FLAG_BZIP2 )
191 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Encoding: bzip2\r\nContent-Length: %zd\r\n\r\n", size );
192 else
193 header_size = sprintf( header, "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r\n", size );
190 194
191 iob_reset( &h->batch ); 195 iob_reset( &h->batch );
192 iob_addbuf_free( &h->batch, header, header_size ); 196 iob_addbuf_free( &h->batch, header, header_size );
@@ -241,9 +245,9 @@ static void senddata( const int64 s, char *buffer, size_t size ) {
241 } 245 }
242} 246}
243 247
244static void httpresponse( const int64 s, char *data _DEBUG_HTTPERROR_PARAM( size_t l ) ) { 248static void httpresponse( const int64 s, char *data, size_t l ) {
245 struct http_data* h = io_getcookie( s ); 249 struct http_data* h = io_getcookie( s );
246 char *c; 250 char *c, *d=data;
247 ot_peer peer; 251 ot_peer peer;
248 ot_torrent *torrent; 252 ot_torrent *torrent;
249 ot_hash *hash = NULL; 253 ot_hash *hash = NULL;
@@ -253,6 +257,9 @@ static void httpresponse( const int64 s, char *data _DEBUG_HTTPERROR_PARAM( size
253 ssize_t len; 257 ssize_t len;
254 size_t reply_size = 0, reply_off; 258 size_t reply_size = 0, reply_off;
255 259
260 /* Touch l and d in case it is unused */
261 l = l; d = d;
262
256#ifdef _DEBUG_HTTPERROR 263#ifdef _DEBUG_HTTPERROR
257 if( l >= sizeof( debug_request ) ) 264 if( l >= sizeof( debug_request ) )
258 l = sizeof( debug_request) - 1; 265 l = sizeof( debug_request) - 1;
@@ -379,6 +386,12 @@ LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] );
379 } 386 }
380 387
381 if( mode == TASK_STATS_TPB ) { 388 if( mode == TASK_STATS_TPB ) {
389#ifdef WANT_COMPRESSION_GZIP
390 if( strnstr( d, "gzip", l ) ) {
391 h->flag |= STRUCT_HTTP_FLAG_GZIP;
392 format |= TASK_FLAG_GZIP;
393 }
394#endif
382 /* Pass this task to the worker thread */ 395 /* Pass this task to the worker thread */
383 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 396 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
384 fullscrape_deliver( s, format ); 397 fullscrape_deliver( s, format );
@@ -403,9 +416,17 @@ LOG_TO_STDERR( "[%08d] scrp: %d.%d.%d.%d - FULL SCRAPE\n", (unsigned int)(g_now
403#ifdef _DEBUG_HTTPERROR 416#ifdef _DEBUG_HTTPERROR
404write( 2, debug_request, l ); 417write( 2, debug_request, l );
405#endif 418#endif
419 format = 0;
420#ifdef WANT_COMPRESSION_GZIP
421 if( strnstr( d, "gzip", l ) ) {
422 h->flag |= STRUCT_HTTP_FLAG_GZIP;
423 format = TASK_FLAG_GZIP;
424 }
425#endif
426
406 /* Pass this task to the worker thread */ 427 /* Pass this task to the worker thread */
407 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 428 h->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
408 fullscrape_deliver( s, TASK_FULLSCRAPE ); 429 fullscrape_deliver( s, TASK_FULLSCRAPE | format );
409 io_dontwantread( s ); 430 io_dontwantread( s );
410 return; 431 return;
411 } 432 }
@@ -655,7 +676,7 @@ static void handle_read( const int64 clientsocket ) {
655 /* If we get the whole request in one packet, handle it without copying */ 676 /* If we get the whole request in one packet, handle it without copying */
656 if( !array_start( &h->request ) ) { 677 if( !array_start( &h->request ) ) {
657 if( memchr( static_inbuf, '\n', l ) ) 678 if( memchr( static_inbuf, '\n', l ) )
658 return httpresponse( clientsocket, static_inbuf _DEBUG_HTTPERROR_PARAM( l ) ); 679 return httpresponse( clientsocket, static_inbuf, l );
659 h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; 680 h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED;
660 return array_catb( &h->request, static_inbuf, l ); 681 return array_catb( &h->request, static_inbuf, l );
661 } 682 }
@@ -670,7 +691,7 @@ static void handle_read( const int64 clientsocket ) {
670 return httperror( clientsocket, "500 request too long", "You sent too much headers"); 691 return httperror( clientsocket, "500 request too long", "You sent too much headers");
671 692
672 if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) 693 if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) )
673 return httpresponse( clientsocket, array_start( &h->request ) _DEBUG_HTTPERROR_PARAM( array_bytes( &h->request ) ) ); 694 return httpresponse( clientsocket, array_start( &h->request ), array_bytes( &h->request ) );
674} 695}
675 696
676static void handle_write( const int64 clientsocket ) { 697static void handle_write( const int64 clientsocket ) {
@@ -722,9 +743,9 @@ static void handle_timeouted( void ) {
722} 743}
723 744
724static void server_mainloop( ) { 745static void server_mainloop( ) {
725 time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 746 time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
726 struct iovec *iovector; 747 struct iovec *iovector;
727 int iovec_entries; 748 int iovec_entries;
728 749
729 for( ; ; ) { 750 for( ; ; ) {
730 int64 i; 751 int64 i;
diff --git a/ot_fullscrape.c b/ot_fullscrape.c
index bb78b8a..d9c872e 100644
--- a/ot_fullscrape.c
+++ b/ot_fullscrape.c
@@ -7,8 +7,12 @@
7#include <string.h> 7#include <string.h>
8#include <pthread.h> 8#include <pthread.h>
9#include <arpa/inet.h> 9#include <arpa/inet.h>
10#ifdef WANT_COMPRESSION_GZIP
11#include <zlib.h>
12#endif
10 13
11/* Libowfat */ 14/* Libowfat */
15#include "byte.h"
12#include "textcode.h" 16#include "textcode.h"
13 17
14/* Opentracker */ 18/* Opentracker */
@@ -24,7 +28,7 @@
24#define OT_SCRAPE_CHUNK_SIZE (512*1024) 28#define OT_SCRAPE_CHUNK_SIZE (512*1024)
25 29
26/* "d8:completei%zde10:downloadedi%zde10:incompletei%zdee" */ 30/* "d8:completei%zde10:downloadedi%zde10:incompletei%zdee" */
27#define OT_FULLSCRAPE_MAXENTRYLEN 100 31#define OT_FULLSCRAPE_MAXENTRYLEN 256
28 32
29/* Forward declaration */ 33/* Forward declaration */
30static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ); 34static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode );
@@ -66,8 +70,12 @@ void fullscrape_deliver( int64 socket, ot_tasktype tasktype ) {
66} 70}
67 71
68static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) { 72static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tasktype mode ) {
69 int bucket; 73 int bucket;
70 char *r, *re; 74 char *r, *re;
75#ifdef WANT_COMPRESSION_GZIP
76 char compress_buffer[OT_FULLSCRAPE_MAXENTRYLEN];
77 z_stream strm;
78#endif
71 79
72 /* Setup return vector... */ 80 /* Setup return vector... */
73 *iovec_entries = 0; 81 *iovec_entries = 0;
@@ -79,8 +87,21 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
79 This works as a low watermark */ 87 This works as a low watermark */
80 re = r + OT_SCRAPE_CHUNK_SIZE; 88 re = r + OT_SCRAPE_CHUNK_SIZE;
81 89
90#ifdef WANT_COMPRESSION_GZIP
91 if( mode & TASK_FLAG_GZIP ) {
92 byte_zero( &strm, sizeof(strm) );
93 strm.next_in = (ot_byte*)r;
94 if( deflateInit2(&strm,9,Z_DEFLATED,31,8,Z_DEFAULT_STRATEGY) != Z_OK )
95 fprintf( stderr, "not ok.\n" );
96
97 strm.next_out = (unsigned char*)r;
98 strm.avail_out = OT_SCRAPE_CHUNK_SIZE;
99 r = compress_buffer;
100 }
101#endif
102
82 /* Reply dictionary only needed for bencoded fullscrape */ 103 /* Reply dictionary only needed for bencoded fullscrape */
83 if( mode == TASK_FULLSCRAPE ) { 104 if( ( mode & TASK_TASK_MASK ) == TASK_FULLSCRAPE ) {
84 memmove( r, "d5:filesd", 9 ); 105 memmove( r, "d5:filesd", 9 );
85 r += 9; 106 r += 9;
86 } 107 }
@@ -97,7 +118,7 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
97 ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[tor_offset] ).peer_list; 118 ot_peerlist *peer_list = ( ((ot_torrent*)(torrents_list->data))[tor_offset] ).peer_list;
98 ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[tor_offset] ).hash; 119 ot_hash *hash =&( ((ot_torrent*)(torrents_list->data))[tor_offset] ).hash;
99 120
100 switch( mode ) { 121 switch( mode & TASK_TASK_MASK ) {
101 case TASK_FULLSCRAPE: 122 case TASK_FULLSCRAPE:
102 default: 123 default:
103 /* push hash as bencoded string */ 124 /* push hash as bencoded string */
@@ -122,6 +143,16 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
122 break; 143 break;
123 } 144 }
124 145
146#ifdef WANT_COMPRESSION_GZIP
147 if( mode & TASK_FLAG_GZIP ) {
148 strm.next_in = (ot_byte*)compress_buffer;
149 strm.avail_in = r - compress_buffer;
150 if( deflate( &strm, Z_NO_FLUSH ) != Z_OK )
151 fprintf( stderr, "Not ok.\n" );
152 r = (char*)strm.next_out;
153 }
154#endif
155
125 /* If we reached our low watermark in buffer... */ 156 /* If we reached our low watermark in buffer... */
126 if( re - r <= OT_FULLSCRAPE_MAXENTRYLEN ) { 157 if( re - r <= OT_FULLSCRAPE_MAXENTRYLEN ) {
127 158
@@ -134,6 +165,10 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
134 /* If this fails: free buffers */ 165 /* If this fails: free buffers */
135 iovec_free( iovec_entries, iovector ); 166 iovec_free( iovec_entries, iovector );
136 167
168#ifdef WANT_COMPRESSION_GZIP
169 deflateEnd(&strm);
170#endif
171
137 /* Release lock on current bucket and return */ 172 /* Release lock on current bucket and return */
138 mutex_bucket_unlock( bucket ); 173 mutex_bucket_unlock( bucket );
139 return; 174 return;
@@ -141,7 +176,19 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
141 176
142 /* Adjust new end of output buffer */ 177 /* Adjust new end of output buffer */
143 re = r + OT_SCRAPE_CHUNK_SIZE; 178 re = r + OT_SCRAPE_CHUNK_SIZE;
179
180#ifdef WANT_COMPRESSION_GZIP
181 if( mode & TASK_FLAG_GZIP ) {
182 strm.next_out = (ot_byte*)r;
183 strm.avail_out = OT_SCRAPE_CHUNK_SIZE;
184 }
185#endif
186 }
187#ifdef WANT_COMPRESSION_GZIP
188 if( mode & TASK_FLAG_GZIP ) {
189 r = compress_buffer;
144 } 190 }
191#endif
145 } 192 }
146 193
147 /* All torrents done: release lock on currenct bucket */ 194 /* All torrents done: release lock on currenct bucket */
@@ -149,10 +196,21 @@ static void fullscrape_make( int *iovec_entries, struct iovec **iovector, ot_tas
149 } 196 }
150 197
151 /* Close bencoded scrape dictionary if necessary */ 198 /* Close bencoded scrape dictionary if necessary */
152 if( mode == TASK_FULLSCRAPE ) { 199 if( ( mode & TASK_TASK_MASK ) == TASK_FULLSCRAPE ) {
153 *r++='e'; *r++='e'; 200 *r++='e'; *r++='e';
154 } 201 }
155 202
203#ifdef WANT_COMPRESSION_GZIP
204 if( mode & TASK_FLAG_GZIP ) {
205 strm.next_in = (ot_byte*) compress_buffer;
206 strm.avail_in = r - compress_buffer;
207 if( deflate( &strm, Z_FINISH ) != Z_STREAM_END )
208 fprintf( stderr, "Not ok.\n" );
209 r = (char*)strm.next_out;
210 deflateEnd(&strm);
211 }
212#endif
213
156 /* Release unused memory in current output buffer */ 214 /* Release unused memory in current output buffer */
157 iovec_fixlast( iovec_entries, iovector, OT_SCRAPE_CHUNK_SIZE - ( re - r ) ); 215 iovec_fixlast( iovec_entries, iovector, OT_SCRAPE_CHUNK_SIZE - ( re - r ) );
158} 216}