summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c91
1 files changed, 53 insertions, 38 deletions
diff --git a/opentracker.c b/opentracker.c
index 7be1421..0ddce0c 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -56,6 +56,7 @@ struct http_data {
56 io_batch batch; 56 io_batch batch;
57 }; 57 };
58 unsigned char ip[4]; 58 unsigned char ip[4];
59 int blessed;
59}; 60};
60 61
61/* Prototypes */ 62/* Prototypes */
@@ -87,6 +88,7 @@ static void graceful( int s );
87#define HTTPERROR_400 return httperror( s, "400 Invalid Request", "This server only understands GET." ) 88#define HTTPERROR_400 return httperror( s, "400 Invalid Request", "This server only understands GET." )
88#define HTTPERROR_400_PARAM return httperror( s, "400 Invalid Request", "Invalid parameter" ) 89#define HTTPERROR_400_PARAM return httperror( s, "400 Invalid Request", "Invalid parameter" )
89#define HTTPERROR_400_COMPACT return httperror( s, "400 Invalid Request", "This server only delivers compact results." ) 90#define HTTPERROR_400_COMPACT return httperror( s, "400 Invalid Request", "This server only delivers compact results." )
91#define HTTPERROR_403_IP return httperror( s, "403 Access Denied", "Your ip address is not allowed to administrate this server." )
90#define HTTPERROR_404 return httperror( s, "404 Not Found", "No such file or directory." ) 92#define HTTPERROR_404 return httperror( s, "404 Not Found", "No such file or directory." )
91#define HTTPERROR_500 return httperror( s, "500 Internal Server Error", "A server error has occured. Please retry later." ) 93#define HTTPERROR_500 return httperror( s, "500 Internal Server Error", "A server error has occured. Please retry later." )
92 94
@@ -173,6 +175,7 @@ static void senddata( const int64 s, char *buffer, size_t size ) {
173} 175}
174 176
175static void httpresponse( const int64 s, char *data ) { 177static void httpresponse( const int64 s, char *data ) {
178 struct http_data* h = io_getcookie( s );
176 char *c, *reply; 179 char *c, *reply;
177 ot_peer peer; 180 ot_peer peer;
178 ot_torrent *torrent; 181 ot_torrent *torrent;
@@ -198,11 +201,48 @@ static void httpresponse( const int64 s, char *data ) {
198 for( c = data+4; *c == '/'; ++c); 201 for( c = data+4; *c == '/'; ++c);
199 202
200 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) { 203 switch( scan_urlencoded_query( &c, data = c, SCAN_PATH ) ) {
204
205/******************************
206 * S Y N C *
207 ******************************/
201 case 4: /* sync ? */ 208 case 4: /* sync ? */
202 if( byte_diff( data, 4, "sync") ) HTTPERROR_404; 209 if( byte_diff( data, 4, "sync") ) HTTPERROR_404;
203 if( !( reply_size = return_changeset_for_tracker( &reply ) ) ) HTTPERROR_500; 210 if( !h->blessed ) HTTPERROR_403_IP;
204 return sendmallocdata( s, reply, reply_size ); 211
212 mode = SYNC_OUT;
213 scanon = 1;
205 214
215 while( scanon ) {
216 switch( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_PARAM ) ) {
217 case -2: scanon = 0; break; /* TERMINATOR */
218 case -1: HTTPERROR_400_PARAM; /* PARSE ERROR */
219 default: scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE ); break;
220 case 9:
221 if(byte_diff(data,9,"changeset")) {
222 scan_urlencoded_query( &c, NULL, SCAN_SEARCHPATH_VALUE );
223 continue;
224 }
225 /* ignore this, when we dont at least see "d4:syncdee" */
226 if( ( len = scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) ) < 10 ) HTTPERROR_400_PARAM;
227 if( add_changeset_to_tracker( (ot_byte*)data, len ) ) HTTPERROR_400_PARAM;
228 mode = SYNC_IN;
229 break;
230 }
231 }
232
233 if( mode == SYNC_OUT ) {
234 if( !( reply_size = return_changeset_for_tracker( &reply ) ) ) HTTPERROR_500;
235 return sendmallocdata( s, reply, reply_size );
236 }
237
238 /* Simple but proof for now */
239 reply = "OK";
240 reply_size = 2;
241
242 break;
243/******************************
244 * S T A T S *
245 ******************************/
206 case 5: /* stats ? */ 246 case 5: /* stats ? */
207 if( byte_diff(data,5,"stats")) HTTPERROR_404; 247 if( byte_diff(data,5,"stats")) HTTPERROR_404;
208 scanon = 1; 248 scanon = 1;
@@ -260,8 +300,11 @@ static void httpresponse( const int64 s, char *data ) {
260 if( !( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, mode ) ) ) HTTPERROR_500; 300 if( !( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, mode ) ) ) HTTPERROR_500;
261 break; 301 break;
262 } 302 }
263
264 break; 303 break;
304
305/******************************
306 * S C R A P E *
307 ******************************/
265 case 6: /* scrape ? */ 308 case 6: /* scrape ? */
266 if( byte_diff( data, 6, "scrape") ) HTTPERROR_404; 309 if( byte_diff( data, 6, "scrape") ) HTTPERROR_404;
267 310
@@ -280,7 +323,7 @@ SCRAPE_WORKAROUND:
280 } 323 }
281 /* ignore this, when we have less than 20 bytes */ 324 /* ignore this, when we have less than 20 bytes */
282 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM; 325 if( scan_urlencoded_query( &c, data = c, SCAN_SEARCHPATH_VALUE ) != 20 ) HTTPERROR_400_PARAM;
283 hash = (ot_hash*)data; /* Fall through intended */ 326 hash = (ot_hash*)data;
284 break; 327 break;
285 } 328 }
286 } 329 }
@@ -297,6 +340,9 @@ SCRAPE_WORKAROUND:
297 340
298 ot_overall_tcp_successfulannounces++; 341 ot_overall_tcp_successfulannounces++;
299 break; 342 break;
343/******************************
344 * A N N O U N C E *
345 ******************************/
300 case 8: 346 case 8:
301 if( byte_diff( data, 8, "announce" ) ) HTTPERROR_404; 347 if( byte_diff( data, 8, "announce" ) ) HTTPERROR_404;
302 348
@@ -384,7 +430,7 @@ ANNOUNCE_WORKAROUND:
384 remove_peer_from_torrent( hash, &peer ); 430 remove_peer_from_torrent( hash, &peer );
385 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM ); 431 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM );
386 } else { 432 } else {
387 torrent = add_peer_to_torrent( hash, &peer ); 433 torrent = add_peer_to_torrent( hash, &peer, 0 );
388 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; 434 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500;
389 } 435 }
390 ot_overall_tcp_successfulannounces++; 436 ot_overall_tcp_successfulannounces++;
@@ -438,12 +484,6 @@ static void graceful( int s ) {
438 484
439static void usage( char *name ) { 485static void usage( char *name ) {
440 fprintf( stderr, "Usage: %s [-i serverip] [-p serverport] [-d serverdirectory]" 486 fprintf( stderr, "Usage: %s [-i serverip] [-p serverport] [-d serverdirectory]"
441#ifdef WANT_CLOSED_TRACKER
442 " [-oc]"
443#endif
444#ifdef WANT_BLACKLIST
445 " [-bB]"
446#endif
447 "\n", name ); 487 "\n", name );
448} 488}
449 489
@@ -453,23 +493,6 @@ static void help( char *name ) {
453 "\t-p serverport\tspecify tcp port to bind to (default: 6969, you may specify more than one)\n" 493 "\t-p serverport\tspecify tcp port to bind to (default: 6969, you may specify more than one)\n"
454 "\t-P serverport\tspecify udp port to bind to (default: 6969, you may specify more than one)\n" 494 "\t-P serverport\tspecify udp port to bind to (default: 6969, you may specify more than one)\n"
455 "\t-d serverdir\tspecify directory containing white- or black listed torrent info_hashes (default: \".\")\n" 495 "\t-d serverdir\tspecify directory containing white- or black listed torrent info_hashes (default: \".\")\n"
456#ifdef WANT_CLOSED_TRACKER
457 "\t-o\t\tmake tracker an open tracker, e.g. do not check for white list (default: off)\n"
458 "\t-c\t\tmake tracker a closed tracker, e.g. check each announced torrent against white list (default: on)\n"
459#endif
460#ifdef WANT_BLACKLIST
461 "\t-b\t\tmake tracker check its black list, e.g. check each announced torrent against black list (default: on)\n"
462 "\t-B\t\tmake tracker check its black list, e.g. check each announced torrent against black list (default: off)\n"
463#endif
464#ifdef WANT_CLOSED_TRACKER
465 "\n* To white list a torrent, touch a file inside serverdir with info_hash hex string.\n"
466#endif
467#ifdef WANT_BLACKLIST
468#ifndef WANT_CLOSED_TRACKER
469 "\n"
470#endif
471 "* To white list a torrent, touch a file inside serverdir with info_hash hex string, preprended by '-'.\n"
472#endif
473 "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -i 10.1.1.23 -p 2710 -p 80\n" 496 "\nExample: ./opentracker -i 127.0.0.1 -p 6969 -P 6969 -i 10.1.1.23 -p 2710 -p 80\n"
474); 497);
475} 498}
@@ -503,7 +526,7 @@ static void handle_read( const int64 clientsocket ) {
503 if( array_failed( &h->request ) ) 526 if( array_failed( &h->request ) )
504 return httperror( clientsocket, "500 Server Error", "Request too long."); 527 return httperror( clientsocket, "500 Server Error", "Request too long.");
505 528
506 if( array_bytes( &h->request ) > 8192 ) 529 if( ( !h->blessed ) && ( array_bytes( &h->request ) > 8192 ) )
507 return httperror( clientsocket, "500 request too long", "You sent too much headers"); 530 return httperror( clientsocket, "500 request too long", "You sent too much headers");
508 531
509 if( memchr( array_start( &h->request ), '\n', array_length( &h->request, 1 ) ) ) 532 if( memchr( array_start( &h->request ), '\n', array_length( &h->request, 1 ) ) )
@@ -626,7 +649,7 @@ static void handle_udp4( int64 serversocket ) {
626 outpacket[3] = outpacket[4] = 0; 649 outpacket[3] = outpacket[4] = 0;
627 r = 20; 650 r = 20;
628 } else { 651 } else {
629 torrent = add_peer_to_torrent( hash, &peer ); 652 torrent = add_peer_to_torrent( hash, &peer, 0 );
630 if( !torrent ) 653 if( !torrent )
631 return; /* XXX maybe send error */ 654 return; /* XXX maybe send error */
632 655
@@ -719,14 +742,6 @@ int main( int argc, char **argv ) {
719 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); break; 742 case 'P': ot_try_bind( serverip, (uint16)atol( optarg ), 0 ); break;
720 case 'd': serverdir = optarg; break; 743 case 'd': serverdir = optarg; break;
721 case 'h': help( argv[0] ); exit( 0 ); 744 case 'h': help( argv[0] ); exit( 0 );
722#ifdef WANT_CLOSED_TRACKER
723 case 'o': g_closedtracker = 0; break;
724 case 'c': g_closedtracker = 1; break;
725#endif
726#ifdef WANT_BLACKLIST
727 case 'b': g_check_blacklist = 1; break;
728 case 'B': g_check_blacklist = 0; break;
729#endif
730 default: 745 default:
731 case '?': usage( argv[0] ); exit( 1 ); 746 case '?': usage( argv[0] ); exit( 1 );
732 } 747 }