summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/opentracker.c b/opentracker.c
index 51a5b33..657f4f3 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -74,6 +74,12 @@ static void handle_timeouted( void );
74static void handle_accept( const int64 serversocket ); 74static void handle_accept( const int64 serversocket );
75static void handle_read( const int64 clientsocket ); 75static void handle_read( const int64 clientsocket );
76static void handle_write( const int64 clientsocket ); 76static void handle_write( const int64 clientsocket );
77static void handle_udp4( const int64 serversocket );
78
79static void ot_try_bind_udp4( char ip[4], uint16 port );
80static void ot_try_bind_tcp4( char ip[4], uint16 port );
81static int ot_in_udp4_sockets( int64 fd );
82static int ot_in_tcp4_sockets( int64 fd );
77 83
78static void usage( char *name ); 84static void usage( char *name );
79static void help( char *name ); 85static void help( char *name );
@@ -381,7 +387,7 @@ ANNOUNCE_WORKAROUND:
381 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM ); 387 reply_size = sprintf( static_outbuf + SUCCESS_HTTP_HEADER_LENGTH, "d8:completei0e10:incompletei0e8:intervali%ie5:peers0:e", OT_CLIENT_REQUEST_INTERVAL_RANDOM );
382 } else { 388 } else {
383 torrent = add_peer_to_torrent( hash, &peer ); 389 torrent = add_peer_to_torrent( hash, &peer );
384 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf ) ) ) HTTPERROR_500; 390 if( !torrent || !( reply_size = return_peers_for_torrent( torrent, numwant, SUCCESS_HTTP_HEADER_LENGTH + static_outbuf, 1 ) ) ) HTTPERROR_500;
385 } 391 }
386 ot_overall_successfulannounces++; 392 ot_overall_successfulannounces++;
387 break; 393 break;
@@ -555,17 +561,76 @@ static void handle_timeouted( void ) {
555 } 561 }
556} 562}
557 563
558void handle_udp4( int64 serversocket ) { 564static void handle_udp4( int64 serversocket ) {
559 size_t r; 565 ot_peer peer;
560 char remoteip[4]; 566 ot_torrent *torrent;
561 uint16 port; 567 ot_hash *hash = NULL;
562 568 char remoteip[4];
563 r = socket_recv4(serversocket, static_inbuf, 8192, remoteip, &port); 569 unsigned long *inpacket = (unsigned long*)static_inbuf;
570 unsigned long *outpacket = (unsigned long*)static_outbuf;
571 unsigned long numwant, left, event;
572 uint16 port;
573 size_t r;
574
575 r = socket_recv4( serversocket, static_inbuf, 8192, remoteip, &port);
576
577 /* Minimum udp tracker packet size, also catches error */
578 if( r < 16 )
579 return;
564 580
565 // too lazy :) 581 switch( ntohl( inpacket[2] ) ) {
582 case 0: /* This is a connect action */
583 outpacket[0] = 0; outpacket[1] = inpacket[3];
584 outpacket[2] = inpacket[0]; outpacket[3] = inpacket[1];
585 socket_send4( serversocket, static_outbuf, 16, remoteip, port );
586 break;
587 case 1: /* This is an announce action */
588 /* Minimum udp announce packet size */
589 if( r < 98 )
590 return;
591
592 numwant = 200;
593 left = ntohl( inpacket[64/4] );
594 event = ntohl( inpacket[80/4] );
595 port = ntohl( inpacket[96/4] );
596 hash = (ot_hash*)inpacket+(16/4);
597
598 OT_SETIP( &peer, remoteip );
599 OT_SETPORT( &peer, &port );
600 OT_FLAG( &peer ) = 0;
601
602 switch( event ) {
603 case 1: OT_FLAG( &peer ) |= PEER_FLAG_COMPLETED; break;
604 case 3: OT_FLAG( &peer ) |= PEER_FLAG_STOPPED; break;
605 default: break;
606 }
607 if( !left )
608 OT_FLAG( &peer ) |= PEER_FLAG_SEEDING;
609
610 if( OT_FLAG( &peer ) & PEER_FLAG_STOPPED ) {
611 /* Peer is gone. */
612 remove_peer_from_torrent( hash, &peer );
613
614 /* Create fake packet to satisfy parser on the other end */
615 outpacket[0] = htonl( 1 );
616 outpacket[1] = inpacket[12/4];
617 outpacket[2] = outpacket[3] = outpacket[4] = 0;
618 socket_send4( serversocket, static_outbuf, 20, remoteip, port );
619 } else {
620 torrent = add_peer_to_torrent( hash, &peer );
621 if( !torrent )
622 return; /* XXX maybe send error */
623
624 outpacket[0] = htonl( 1 );
625 outpacket[1] = inpacket[12/4];
626 r = 8 + return_peers_for_torrent( torrent, numwant, static_outbuf + 8, 0 );
627 socket_send4( serversocket, static_outbuf, r, remoteip, port );
628 }
629 break;
630 }
566} 631}
567 632
568int ot_in_tcp4_sockets( int64 fd ) { 633static int ot_in_tcp4_sockets( int64 fd ) {
569 int i; 634 int i;
570 for( i=0; i<ot_sockets_tcp4_count; ++i) 635 for( i=0; i<ot_sockets_tcp4_count; ++i)
571 if( ot_sockets_tcp4[i] == fd ) 636 if( ot_sockets_tcp4[i] == fd )
@@ -573,7 +638,7 @@ int ot_in_tcp4_sockets( int64 fd ) {
573 return 0; 638 return 0;
574} 639}
575 640
576int ot_in_udp4_sockets( int64 fd ) { 641static int ot_in_udp4_sockets( int64 fd ) {
577 int i; 642 int i;
578 for( i=0; i<ot_sockets_udp4_count; ++i) 643 for( i=0; i<ot_sockets_udp4_count; ++i)
579 if( ot_sockets_udp4[i] == fd ) 644 if( ot_sockets_udp4[i] == fd )
@@ -614,7 +679,7 @@ static void server_mainloop( ) {
614 } 679 }
615} 680}
616 681
617void ot_try_bind_tcp4( char ip[4], uint16 port ) { 682static void ot_try_bind_tcp4( char ip[4], uint16 port ) {
618 int64 s = socket_tcp4( ); 683 int64 s = socket_tcp4( );
619 if( ot_sockets_tcp4_count == OT_MAXSOCKETS_TCP4 ) { 684 if( ot_sockets_tcp4_count == OT_MAXSOCKETS_TCP4 ) {
620 fprintf( stderr, "Too many tcp4 sockets, increase OT_MAXSOCKETS_TCP4 and recompile.\n"); exit(1); 685 fprintf( stderr, "Too many tcp4 sockets, increase OT_MAXSOCKETS_TCP4 and recompile.\n"); exit(1);
@@ -633,7 +698,7 @@ void ot_try_bind_tcp4( char ip[4], uint16 port ) {
633 ot_sockets_tcp4[ ot_sockets_tcp4_count++ ] = s; 698 ot_sockets_tcp4[ ot_sockets_tcp4_count++ ] = s;
634} 699}
635 700
636void ot_try_bind_udp4( char ip[4], uint16 port ) { 701static void ot_try_bind_udp4( char ip[4], uint16 port ) {
637 int64 s = socket_udp4( ); 702 int64 s = socket_udp4( );
638 if( ot_sockets_udp4_count == OT_MAXSOCKETS_UDP4 ) { 703 if( ot_sockets_udp4_count == OT_MAXSOCKETS_UDP4 ) {
639 fprintf( stderr, "Too many udp4 sockets, increase OT_MAXSOCKETS_UDP4 and recompile.\n"); exit(1); 704 fprintf( stderr, "Too many udp4 sockets, increase OT_MAXSOCKETS_UDP4 and recompile.\n"); exit(1);
@@ -655,7 +720,7 @@ int main( int argc, char **argv ) {
655 int scanon = 1; 720 int scanon = 1;
656 721
657 while( scanon ) { 722 while( scanon ) {
658 switch( getopt( argc, argv, ":i:p:d:ocbBh" ) ) { 723 switch( getopt( argc, argv, ":i:p:P:d:ocbBh" ) ) {
659 case -1 : scanon = 0; break; 724 case -1 : scanon = 0; break;
660 case 'i': scan_ip4( optarg, serverip ); break; 725 case 'i': scan_ip4( optarg, serverip ); break;
661 case 'p': ot_try_bind_tcp4( serverip, (uint16)atol( optarg ) ); break; 726 case 'p': ot_try_bind_tcp4( serverip, (uint16)atol( optarg ) ); break;