diff options
-rw-r--r-- | opentracker.c | 91 | ||||
-rw-r--r-- | trackerlogic.c | 15 | ||||
-rw-r--r-- | trackerlogic.h | 4 |
3 files changed, 92 insertions, 18 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 ); | |||
74 | static void handle_accept( const int64 serversocket ); | 74 | static void handle_accept( const int64 serversocket ); |
75 | static void handle_read( const int64 clientsocket ); | 75 | static void handle_read( const int64 clientsocket ); |
76 | static void handle_write( const int64 clientsocket ); | 76 | static void handle_write( const int64 clientsocket ); |
77 | static void handle_udp4( const int64 serversocket ); | ||
78 | |||
79 | static void ot_try_bind_udp4( char ip[4], uint16 port ); | ||
80 | static void ot_try_bind_tcp4( char ip[4], uint16 port ); | ||
81 | static int ot_in_udp4_sockets( int64 fd ); | ||
82 | static int ot_in_tcp4_sockets( int64 fd ); | ||
77 | 83 | ||
78 | static void usage( char *name ); | 84 | static void usage( char *name ); |
79 | static void help( char *name ); | 85 | static 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 | ||
558 | void handle_udp4( int64 serversocket ) { | 564 | static 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 | ||
568 | int ot_in_tcp4_sockets( int64 fd ) { | 633 | static 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 | ||
576 | int ot_in_udp4_sockets( int64 fd ) { | 641 | static 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 | ||
617 | void ot_try_bind_tcp4( char ip[4], uint16 port ) { | 682 | static 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 | ||
636 | void ot_try_bind_udp4( char ip[4], uint16 port ) { | 701 | static 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; |
diff --git a/trackerlogic.c b/trackerlogic.c index 18e8cf5..a2cd1ab 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -269,7 +269,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | |||
269 | * RANDOM may return huge values | 269 | * RANDOM may return huge values |
270 | * does not yet check not to return self | 270 | * does not yet check not to return self |
271 | */ | 271 | */ |
272 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply ) { | 272 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ) { |
273 | char *r = reply; | 273 | char *r = reply; |
274 | size_t peer_count, seed_count, index; | 274 | size_t peer_count, seed_count, index; |
275 | 275 | ||
@@ -295,7 +295,15 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
295 | } | 295 | } |
296 | if( peer_count < amount ) amount = peer_count; | 296 | if( peer_count < amount ) amount = peer_count; |
297 | 297 | ||
298 | r += sprintf( r, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers%zd:", seed_count, peer_count-seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount ); | 298 | if( is_tcp ) |
299 | r += sprintf( r, "d8:completei%zde10:incompletei%zde8:intervali%ie5:peers%zd:", seed_count, peer_count-seed_count, OT_CLIENT_REQUEST_INTERVAL_RANDOM, 6*amount ); | ||
300 | else { | ||
301 | *(unsigned long*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM ); | ||
302 | *(unsigned long*)(r+4) = htonl( peer_count ); | ||
303 | *(unsigned long*)(r+8) = htonl( seed_count ); | ||
304 | r += 12; | ||
305 | } | ||
306 | |||
299 | if( amount ) { | 307 | if( amount ) { |
300 | unsigned int pool_offset, pool_index = 0;; | 308 | unsigned int pool_offset, pool_index = 0;; |
301 | unsigned int shifted_pc = peer_count; | 309 | unsigned int shifted_pc = peer_count; |
@@ -327,7 +335,8 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
327 | r += 6; | 335 | r += 6; |
328 | } | 336 | } |
329 | } | 337 | } |
330 | *r++ = 'e'; | 338 | if( is_tcp ) |
339 | *r++ = 'e'; | ||
331 | 340 | ||
332 | return r - reply; | 341 | return r - reply; |
333 | } | 342 | } |
diff --git a/trackerlogic.h b/trackerlogic.h index 5c83f63..360dacb 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
@@ -94,12 +94,12 @@ extern int g_check_blacklist; | |||
94 | enum { STATS_MRTG, STATS_TOP5, STATS_DMEM }; | 94 | enum { STATS_MRTG, STATS_TOP5, STATS_DMEM }; |
95 | 95 | ||
96 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ); | 96 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ); |
97 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply ); | 97 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ); |
98 | size_t return_fullscrape_for_tracker( char **reply ); | 98 | size_t return_fullscrape_for_tracker( char **reply ); |
99 | size_t return_scrape_for_torrent( ot_hash *hash, char *reply ); | 99 | size_t return_scrape_for_torrent( ot_hash *hash, char *reply ); |
100 | size_t return_sync_for_torrent( ot_hash *hash, char **reply ); | 100 | size_t return_sync_for_torrent( ot_hash *hash, char **reply ); |
101 | size_t return_stats_for_tracker( char *reply, int mode ); | 101 | size_t return_stats_for_tracker( char *reply, int mode ); |
102 | size_t return_memstat_for_tracker( char **reply ); | 102 | size_t return_memstat_for_tracker( char **reply ); |
103 | void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ); | 103 | void remove_peer_from_torrent( ot_hash *hash, ot_peer *peer ); |
104 | 104 | ||
105 | #endif | 105 | #endif |