summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c192
1 files changed, 27 insertions, 165 deletions
diff --git a/opentracker.c b/opentracker.c
index 0345177..6bde42e 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -3,17 +3,7 @@
3 Some of the stuff below is stolen from Fefes example libowfat httpd. 3 Some of the stuff below is stolen from Fefes example libowfat httpd.
4*/ 4*/
5 5
6#include "socket.h" 6/* System */
7#include "io.h"
8#include "iob.h"
9#include "buffer.h"
10#include "array.h"
11#include "byte.h"
12#include "case.h"
13#include "fmt.h"
14#include "str.h"
15#include "scan.h"
16#include "ip4.h"
17#include <string.h> 7#include <string.h>
18#include <sys/types.h> 8#include <sys/types.h>
19#include <sys/stat.h> 9#include <sys/stat.h>
@@ -27,23 +17,32 @@
27#include <stdio.h> 17#include <stdio.h>
28#include <pwd.h> 18#include <pwd.h>
29 19
20/* Libowfat */
21#include "socket.h"
22#include "io.h"
23#include "iob.h"
24#include "buffer.h"
25#include "array.h"
26#include "byte.h"
27#include "case.h"
28#include "fmt.h"
29#include "str.h"
30#include "scan.h"
31#include "ip4.h"
32
33/* Opentracker */
30#include "trackerlogic.h" 34#include "trackerlogic.h"
31#include "scan_urlencoded_query.h" 35#include "scan_urlencoded_query.h"
32#include "ot_stats.h" 36#include "ot_stats.h"
33#include "ot_sync.h" 37#include "ot_sync.h"
38#include "ot_udp.h"
34 39
35/* Globals */ 40/* Globals */
36static unsigned long long ot_overall_tcp_connections = 0;
37static unsigned long long ot_overall_udp_connections = 0;
38static unsigned long long ot_overall_tcp_successfulannounces = 0;
39static unsigned long long ot_overall_udp_successfulannounces = 0;
40static unsigned long long ot_full_scrape_count = 0;
41static unsigned long long ot_full_scrape_size = 0;
42static time_t ot_start_time;
43static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80; 41static const size_t SUCCESS_HTTP_HEADER_LENGTH = 80;
44static const size_t SUCCESS_HTTP_SIZE_OFF = 17; 42static const size_t SUCCESS_HTTP_SIZE_OFF = 17;
45static uint32_t g_adminip_addresses[OT_ADMINIP_MAX]; 43static uint32_t g_adminip_addresses[OT_ADMINIP_MAX];
46static unsigned int g_adminip_count = 0; 44static unsigned int g_adminip_count = 0;
45time_t ot_start_time;
47time_t g_now; 46time_t g_now;
48 47
49#if defined ( WANT_BLACKLISTING ) && defined (WANT_CLOSED_TRACKER ) 48#if defined ( WANT_BLACKLISTING ) && defined (WANT_CLOSED_TRACKER )
@@ -65,9 +64,8 @@ static char *accesslist_filename = NULL;
65#endif 64#endif
66 65
67/* To always have space for error messages ;) */ 66/* To always have space for error messages ;) */
68 67char static_inbuf[8192];
69static char static_inbuf[8192]; 68char static_outbuf[8192];
70static char static_outbuf[8192];
71 69
72#define OT_MAXMULTISCRAPE_COUNT 64 70#define OT_MAXMULTISCRAPE_COUNT 64
73static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT]; 71static ot_hash multiscrape_buf[OT_MAXMULTISCRAPE_COUNT];
@@ -114,7 +112,6 @@ static void handle_timeouted( void );
114static void handle_accept( const int64 serversocket ); 112static void handle_accept( const int64 serversocket );
115static void handle_read( const int64 clientsocket ); 113static void handle_read( const int64 clientsocket );
116static void handle_write( const int64 clientsocket ); 114static void handle_write( const int64 clientsocket );
117static void handle_udp4( const int64 serversocket );
118 115
119static void ot_try_bind( char ip[4], uint16 port, int is_tcp ); 116static void ot_try_bind( char ip[4], uint16 port, int is_tcp );
120 117
@@ -234,7 +231,6 @@ static void httpresponse( const int64 s, char *data _DEBUG_HTTPERROR_PARAM( size
234 ot_hash *hash = NULL; 231 ot_hash *hash = NULL;
235 int numwant, tmp, scanon, mode; 232 int numwant, tmp, scanon, mode;
236 unsigned short port = htons(6881); 233 unsigned short port = htons(6881);
237 time_t t;
238 ssize_t len; 234 ssize_t len;
239 size_t reply_size = 0, reply_off; 235 size_t reply_size = 0, reply_off;
240 236
@@ -347,47 +343,9 @@ LOG_TO_STDERR( "sync: %d.%d.%d.%d\n", h->ip[0], h->ip[1], h->ip[2], h->ip[3] );
347 case STATS_DMEM: 343 case STATS_DMEM:
348 if( !( reply_size = return_memstat_for_tracker( &reply ) ) ) HTTPERROR_500; 344 if( !( reply_size = return_memstat_for_tracker( &reply ) ) ) HTTPERROR_500;
349 return sendmmapdata( s, reply, reply_size ); 345 return sendmmapdata( s, reply, reply_size );
350
351 case STATS_CONNS:
352 t = time( NULL ) - ot_start_time;
353 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH,
354 "%llu\n%llu\n%i seconds (%i hours)\nopentracker - Pretuned by german engineers, currently handling %llu connections per second.",
355 ot_overall_tcp_connections+ot_overall_udp_connections, ot_overall_tcp_successfulannounces+ot_overall_udp_successfulannounces, (int)t, (int)(t / 3600), (ot_overall_tcp_connections+ot_overall_udp_connections) / ( (unsigned int)t ? (unsigned int)t : 1 ) );
356 break;
357 case STATS_UDP:
358 t = time( NULL ) - ot_start_time;
359 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH,
360 "%llu\n%llu\n%i seconds (%i hours)\nopentracker udp4 stats.",
361 ot_overall_udp_connections, ot_overall_udp_successfulannounces, (int)t, (int)(t / 3600) );
362 break;
363
364 case STATS_TCP:
365 t = time( NULL ) - ot_start_time;
366 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH,
367 "%llu\n%llu\n%i seconds (%i hours)\nopentracker tcp4 stats.",
368 ot_overall_tcp_connections, ot_overall_tcp_successfulannounces, (int)t, (int)(t / 3600) );
369 break;
370
371 default: 346 default:
372 case STATS_PEERS: 347 // default format for now
373 /* Enough for http header + whole scrape string */ 348 if( !( reply_size = return_stats_for_tracker( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, mode, 0 ) ) ) HTTPERROR_500;
374 if( !( reply_size = return_stats_for_tracker( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, mode ) ) ) HTTPERROR_500;
375 break;
376
377 case STATS_FULLSCRAPE:
378 t = time( NULL ) - ot_start_time;
379 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH,
380 "%llu\n%llu\n%i seconds (%i hours)\nopentracker full scrape stats.",
381 ot_full_scrape_count * 1000, ot_full_scrape_size, (int)t, (int)(t / 3600) );
382 break;
383
384 case STATS_SLASH24S:
385 {
386 ot_dword diff; struct timeval tv1, tv2; gettimeofday( &tv1, NULL );
387 if( !( reply_size = return_stats_for_slash24s( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 25, 16 ) ) ) HTTPERROR_500;
388 gettimeofday( &tv2, NULL ); diff = ( tv2.tv_sec - tv1.tv_sec ) * 1000000 + tv2.tv_usec - tv1.tv_usec;
389 reply_size += sprintf( SUCCESS_HTTP_HEADER_LENGTH + static_outbuf + reply_size, "Time taken: %u\n", diff );
390 }
391 break; 349 break;
392 } 350 }
393 break; 351 break;
@@ -409,10 +367,7 @@ write( 2, debug_request, l );
409 if( !( reply_size = return_fullscrape_for_tracker( &reply ) ) ) HTTPERROR_500; 367 if( !( reply_size = return_fullscrape_for_tracker( &reply ) ) ) HTTPERROR_500;
410 368
411 /* Stat keeping */ 369 /* Stat keeping */
412 ot_overall_tcp_successfulannounces++; 370 stats_issue_event( EVENT_FULLSCRAPE, 1, reply_size);
413 ot_full_scrape_count++;
414 ot_full_scrape_size += reply_size;
415
416 return sendmmapdata( s, reply, reply_size ); 371 return sendmmapdata( s, reply, reply_size );
417 } 372 }
418 373
@@ -460,8 +415,7 @@ UTORRENT1600_WORKAROUND:
460 415
461 /* Enough for http header + whole scrape string */ 416 /* Enough for http header + whole scrape string */
462 if( !( reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; 417 if( !( reply_size = return_tcp_scrape_for_torrent( multiscrape_buf, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500;
463 418 stats_issue_event( EVENT_SCRAPE, 1, reply_size );
464 ot_overall_tcp_successfulannounces++;
465 break; 419 break;
466/****************************** 420/******************************
467 * A N N O U N C E * 421 * A N N O U N C E *
@@ -564,7 +518,7 @@ ANNOUNCE_WORKAROUND:
564 torrent = add_peer_to_torrent( hash, &peer, 0 ); 518 torrent = add_peer_to_torrent( hash, &peer, 0 );
565 if( !torrent || !( reply_size = return_peers_for_torrent( hash, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500; 519 if( !torrent || !( reply_size = return_peers_for_torrent( hash, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500;
566 } 520 }
567 ot_overall_tcp_successfulannounces++; 521 stats_issue_event( EVENT_ANNOUNCE, 1, reply_size);
568 break; 522 break;
569 default: 523 default:
570 if( ( *data == 'a' ) || ( *data == '?' ) ) goto ANNOUNCE_WORKAROUND; 524 if( ( *data == 'a' ) || ( *data == '?' ) ) goto ANNOUNCE_WORKAROUND;
@@ -702,14 +656,13 @@ static void handle_accept( const int64 serversocket ) {
702 byte_zero( h, sizeof( struct http_data ) ); 656 byte_zero( h, sizeof( struct http_data ) );
703 memmove( h->ip, ip, sizeof( ip ) ); 657 memmove( h->ip, ip, sizeof( ip ) );
704 658
705 ++ot_overall_tcp_connections; 659 stats_issue_event( EVENT_ACCEPT, 1, 0);
706 660
707 /* That breaks taia encapsulation. But there is no way to take system 661 /* That breaks taia encapsulation. But there is no way to take system
708 time this often in FreeBSD and libowfat does not allow to set unix time */ 662 time this often in FreeBSD and libowfat does not allow to set unix time */
709 taia_uint( &t, 0 ); /* Clear t */ 663 taia_uint( &t, 0 ); /* Clear t */
710 tai_unix( &(t.sec), (g_now + OT_CLIENT_TIMEOUT) ); 664 tai_unix( &(t.sec), (g_now + OT_CLIENT_TIMEOUT) );
711 io_timeout( i, t ); 665 io_timeout( i, t );
712
713 } 666 }
714 667
715 if( errno == EAGAIN ) 668 if( errno == EAGAIN )
@@ -731,94 +684,6 @@ static void handle_timeouted( void ) {
731 } 684 }
732} 685}
733 686
734/* UDP implementation according to http://xbtt.sourceforge.net/udp_tracker_protocol.html */
735
736static void handle_udp4( int64 serversocket ) {
737 ot_peer peer;
738 ot_torrent *torrent;
739 ot_hash *hash = NULL;
740 char remoteip[4];
741 ot_dword *inpacket = (ot_dword*)static_inbuf;
742 ot_dword *outpacket = (ot_dword*)static_outbuf;
743 ot_dword numwant, left, event;
744 ot_word port, remoteport;
745 size_t r, r_out;
746
747 r = socket_recv4( serversocket, static_inbuf, 8192, remoteip, &remoteport);
748
749 ot_overall_udp_connections++;
750
751 /* Minimum udp tracker packet size, also catches error */
752 if( r < 16 )
753 return;
754
755 /* look for udp bittorrent magic id */
756 if( (ntohl(inpacket[0]) != 0x00000417) || (ntohl(inpacket[1]) != 0x27101980) )
757 return;
758
759 switch( ntohl( inpacket[2] ) ) {
760 case 0: /* This is a connect action */
761 outpacket[0] = 0; outpacket[1] = inpacket[3];
762 outpacket[2] = inpacket[0]; outpacket[3] = inpacket[1];
763 socket_send4( serversocket, static_outbuf, 16, remoteip, remoteport );
764 ot_overall_udp_successfulannounces++;
765 break;
766 case 1: /* This is an announce action */
767 /* Minimum udp announce packet size */
768 if( r < 98 )
769 return;
770
771 numwant = 200;
772 /* We do only want to know, if it is zero */
773 left = inpacket[64/4] | inpacket[68/4];
774
775 event = ntohl( inpacket[80/4] );
776 port = *(ot_word*)( static_inbuf + 96 );
777 hash = (ot_hash*)( static_inbuf + 16 );
778
779 OT_SETIP( &peer, remoteip );
780 OT_SETPORT( &peer, &port );
781 OT_FLAG( &peer ) = 0;
782
783 switch( event ) {
784 case 1: OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED; break;
785 case 3: OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; break;
786 default: break;
787 }
788
789 if( !left )
790 OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
791
792 outpacket[0] = htonl( 1 ); /* announce action */
793 outpacket[1] = inpacket[12/4];
794
795 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) /* Peer is gone. */
796 r = remove_peer_from_torrent( hash, &peer, static_outbuf, 0 );
797 else {
798 torrent = add_peer_to_torrent( hash, &peer, 0 );
799 if( !torrent )
800 return; /* XXX maybe send error */
801
802 r = 8 + return_peers_for_torrent( hash, numwant, static_outbuf + 8, 0 );
803 }
804
805 socket_send4( serversocket, static_outbuf, r, remoteip, remoteport );
806 ot_overall_udp_successfulannounces++;
807 break;
808
809 case 2: /* This is a scrape action */
810 outpacket[0] = htonl( 2 ); /* scrape action */
811 outpacket[1] = inpacket[12/4];
812
813 for( r_out = 0; ( r_out * 20 < r - 16) && ( r_out <= 74 ); r_out++ )
814 return_udp_scrape_for_torrent( (ot_hash*)( static_inbuf + 16 + 20 * r_out ), static_outbuf + 8 + 12 * r_out );
815
816 socket_send4( serversocket, static_outbuf, 8 + 12 * r_out, remoteip, remoteport );
817 ot_overall_udp_successfulannounces++;
818 break;
819 }
820}
821
822static void server_mainloop( ) { 687static void server_mainloop( ) {
823 time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 688 time_t next_timeout_check = g_now + OT_CLIENT_TIMEOUT_CHECKINTERVAL;
824 689
@@ -892,17 +757,14 @@ void read_accesslist_file( int foo ) {
892 for( i=0; i<20; ++i ) { 757 for( i=0; i<20; ++i ) {
893 int eger = 16 * scan_fromhex( static_inbuf[ 2*i ] ) + scan_fromhex( static_inbuf[ 1 + 2*i ] ); 758 int eger = 16 * scan_fromhex( static_inbuf[ 2*i ] ) + scan_fromhex( static_inbuf[ 1 + 2*i ] );
894 if( eger < 0 ) 759 if( eger < 0 )
895 goto ignore_line; 760 continue;
896 infohash[i] = eger; 761 infohash[i] = eger;
897 } 762 }
898 if( scan_fromhex( static_inbuf[ 40 ] ) >= 0 ) 763 if( scan_fromhex( static_inbuf[ 40 ] ) >= 0 )
899 goto ignore_line; 764 continue;
900 765
901 /* Append accesslist to accesslist vector */ 766 /* Append accesslist to accesslist vector */
902 accesslist_addentry( &infohash ); 767 accesslist_addentry( &infohash );
903
904ignore_line:
905 continue;
906 } 768 }
907 769
908 fclose( accesslist_filehandle ); 770 fclose( accesslist_filehandle );