diff options
-rw-r--r-- | opentracker.c | 31 | ||||
-rw-r--r-- | trackerlogic.c | 133 | ||||
-rw-r--r-- | trackerlogic.h | 7 |
3 files changed, 93 insertions, 78 deletions
diff --git a/opentracker.c b/opentracker.c index d9336da..bf9db89 100644 --- a/opentracker.c +++ b/opentracker.c | |||
@@ -49,6 +49,10 @@ static char *accesslist_filename = NULL; | |||
49 | #define WANT_ACCESS_CONTROL | 49 | #define WANT_ACCESS_CONTROL |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifndef WANT_TRACKER_SYNC | ||
53 | #define add_peer_to_torrent(A,B,C) add_peer_to_torrent(A,B) | ||
54 | #endif | ||
55 | |||
52 | #ifndef NO_FULLSCRAPE_LOGGING | 56 | #ifndef NO_FULLSCRAPE_LOGGING |
53 | #define LOG_TO_STDERR( ... ) fprintf( stderr, __VA_ARGS__ ) | 57 | #define LOG_TO_STDERR( ... ) fprintf( stderr, __VA_ARGS__ ) |
54 | #else | 58 | #else |
@@ -91,7 +95,12 @@ struct http_data { | |||
91 | int main( int argc, char **argv ); | 95 | int main( int argc, char **argv ); |
92 | 96 | ||
93 | static void httperror( const int64 s, const char *title, const char *message ); | 97 | static void httperror( const int64 s, const char *title, const char *message ); |
98 | |||
99 | #ifdef _DEBUG_HTTPERROR | ||
94 | static void httpresponse( const int64 s, char *data, size_t l ); | 100 | static void httpresponse( const int64 s, char *data, size_t l ); |
101 | #else | ||
102 | static void httpresponse( const int64 s, char *data ); | ||
103 | #endif | ||
95 | 104 | ||
96 | static void sendmmapdata( const int64 s, char *buffer, const size_t size ); | 105 | static void sendmmapdata( const int64 s, char *buffer, const size_t size ); |
97 | static void senddata( const int64 s, char *buffer, const size_t size ); | 106 | static void senddata( const int64 s, char *buffer, const size_t size ); |
@@ -213,7 +222,11 @@ static void senddata( const int64 s, char *buffer, size_t size ) { | |||
213 | } | 222 | } |
214 | } | 223 | } |
215 | 224 | ||
225 | #ifdef _DEBUG_HTTPERROR | ||
216 | static void httpresponse( const int64 s, char *data, size_t l ) { | 226 | static void httpresponse( const int64 s, char *data, size_t l ) { |
227 | #else | ||
228 | static void httpresponse( const int64 s, char *data ) { | ||
229 | #endif | ||
217 | struct http_data* h = io_getcookie( s ); | 230 | struct http_data* h = io_getcookie( s ); |
218 | char *c, *reply; | 231 | char *c, *reply; |
219 | ot_peer peer; | 232 | ot_peer peer; |
@@ -643,8 +656,13 @@ static void handle_read( const int64 clientsocket ) { | |||
643 | 656 | ||
644 | /* If we get the whole request in one packet, handle it without copying */ | 657 | /* If we get the whole request in one packet, handle it without copying */ |
645 | if( !array_start( &h->request ) ) { | 658 | if( !array_start( &h->request ) ) { |
646 | if( memchr( static_inbuf, '\n', l ) ) | 659 | if( memchr( static_inbuf, '\n', l ) ) { |
647 | return httpresponse( clientsocket, static_inbuf, l ); | 660 | return httpresponse( clientsocket, static_inbuf |
661 | #ifdef _DEBUG_HTTPERROR | ||
662 | , l | ||
663 | #endif | ||
664 | ); | ||
665 | } | ||
648 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; | 666 | h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; |
649 | return array_catb( &h->request, static_inbuf, l ); | 667 | return array_catb( &h->request, static_inbuf, l ); |
650 | } | 668 | } |
@@ -658,8 +676,13 @@ static void handle_read( const int64 clientsocket ) { | |||
658 | if( ( array_bytes( &h->request ) > 8192 ) && NOTBLESSED( h ) ) | 676 | if( ( array_bytes( &h->request ) > 8192 ) && NOTBLESSED( h ) ) |
659 | return httperror( clientsocket, "500 request too long", "You sent too much headers"); | 677 | return httperror( clientsocket, "500 request too long", "You sent too much headers"); |
660 | 678 | ||
661 | if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) | 679 | if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) { |
662 | return httpresponse( clientsocket, array_start( &h->request ), array_bytes( &h->request ) ); | 680 | return httpresponse( clientsocket, array_start( &h->request ) |
681 | #ifdef _DEBUG_HTTPERROR | ||
682 | , array_bytes( &h->request ) | ||
683 | #endif | ||
684 | ); | ||
685 | } | ||
663 | } | 686 | } |
664 | 687 | ||
665 | static void handle_write( const int64 clientsocket ) { | 688 | static void handle_write( const int64 clientsocket ) { |
diff --git a/trackerlogic.c b/trackerlogic.c index 3aa3752..fd34d28 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
@@ -22,14 +22,11 @@ | |||
22 | /* GLOBAL VARIABLES */ | 22 | /* GLOBAL VARIABLES */ |
23 | static ot_vector all_torrents[OT_BUCKET_COUNT]; | 23 | static ot_vector all_torrents[OT_BUCKET_COUNT]; |
24 | static ot_time all_torrents_clean[OT_BUCKET_COUNT]; | 24 | static ot_time all_torrents_clean[OT_BUCKET_COUNT]; |
25 | static ot_vector changeset; | ||
26 | #if defined ( WANT_BLACKLISTING ) || defined( WANT_CLOSED_TRACKER ) | 25 | #if defined ( WANT_BLACKLISTING ) || defined( WANT_CLOSED_TRACKER ) |
27 | static ot_vector accesslist; | 26 | static ot_vector accesslist; |
28 | #define WANT_ACCESS_CONTROL | 27 | #define WANT_ACCESS_CONTROL |
29 | #endif | 28 | #endif |
30 | 29 | ||
31 | static size_t changeset_size = 0; | ||
32 | |||
33 | static int clean_single_torrent( ot_torrent *torrent ); | 30 | static int clean_single_torrent( ot_torrent *torrent ); |
34 | 31 | ||
35 | /* Converter function from memory to human readable hex strings | 32 | /* Converter function from memory to human readable hex strings |
@@ -126,6 +123,9 @@ static void free_peerlist( ot_peerlist *peer_list ) { | |||
126 | for( i=0; i<OT_POOLS_COUNT; ++i ) | 123 | for( i=0; i<OT_POOLS_COUNT; ++i ) |
127 | if( peer_list->peers[i].data ) | 124 | if( peer_list->peers[i].data ) |
128 | free( peer_list->peers[i].data ); | 125 | free( peer_list->peers[i].data ); |
126 | #ifdef WANT_TRACKER_SYNC | ||
127 | free( peer_list->changeset.data ); | ||
128 | #endif | ||
129 | free( peer_list ); | 129 | free( peer_list ); |
130 | } | 130 | } |
131 | 131 | ||
@@ -145,7 +145,11 @@ static void vector_remove_torrent( ot_vector *vector, ot_torrent *match ) { | |||
145 | } | 145 | } |
146 | } | 146 | } |
147 | 147 | ||
148 | #ifdef WANT_TRACKER_SYNC | ||
148 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) { | 149 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) { |
150 | #else | ||
151 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | ||
152 | #endif | ||
149 | int exactmatch; | 153 | int exactmatch; |
150 | ot_torrent *torrent; | 154 | ot_torrent *torrent; |
151 | ot_peer *peer_dest; | 155 | ot_peer *peer_dest; |
@@ -184,6 +188,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changese | |||
184 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) | 188 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) |
185 | OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; | 189 | OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; |
186 | 190 | ||
191 | #ifdef WANT_TRACKER_SYNC | ||
187 | if( from_changeset ) { | 192 | if( from_changeset ) { |
188 | /* Check, whether peer already is in current pool, do nothing if so */ | 193 | /* Check, whether peer already is in current pool, do nothing if so */ |
189 | peer_pool = &torrent->peer_list->peers[0]; | 194 | peer_pool = &torrent->peer_list->peers[0]; |
@@ -192,6 +197,7 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changese | |||
192 | return torrent; | 197 | return torrent; |
193 | base_pool = 1; | 198 | base_pool = 1; |
194 | } | 199 | } |
200 | #endif | ||
195 | 201 | ||
196 | peer_pool = &torrent->peer_list->peers[ base_pool ]; | 202 | peer_pool = &torrent->peer_list->peers[ base_pool ]; |
197 | peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); | 203 | peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); |
@@ -431,54 +437,6 @@ size_t return_tcp_scrape_for_torrent( ot_hash *hash_list, int amount, char *repl | |||
431 | } | 437 | } |
432 | 438 | ||
433 | #ifdef WANT_TRACKER_SYNC | 439 | #ifdef WANT_TRACKER_SYNC |
434 | /* Throw away old changeset */ | ||
435 | static void release_changeset( void ) { | ||
436 | ot_byte **changeset_ptrs = (ot_byte**)(changeset.data); | ||
437 | size_t i; | ||
438 | |||
439 | for( i = 0; i < changeset.size; ++i ) | ||
440 | free( changeset_ptrs[i] ); | ||
441 | |||
442 | free( changeset_ptrs ); | ||
443 | byte_zero( &changeset, sizeof( changeset ) ); | ||
444 | |||
445 | changeset_size = 0; | ||
446 | } | ||
447 | |||
448 | static void add_pool_to_changeset( ot_hash *hash, ot_peer *peers, size_t peer_count ) { | ||
449 | ot_byte *pool_copy = (ot_byte *)malloc( sizeof( size_t ) + sizeof( ot_hash ) + sizeof( ot_peer ) * peer_count + 13 ); | ||
450 | size_t r = 0; | ||
451 | |||
452 | if( !pool_copy ) | ||
453 | return; | ||
454 | |||
455 | memmove( pool_copy + sizeof( size_t ), "20:", 3 ); | ||
456 | memmove( pool_copy + sizeof( size_t ) + 3, hash, sizeof( ot_hash ) ); | ||
457 | r = sizeof( size_t ) + 3 + sizeof( ot_hash ); | ||
458 | r += sprintf( (char*)pool_copy + r, "%zd:", sizeof( ot_peer ) * peer_count ); | ||
459 | memmove( pool_copy + r, peers, sizeof( ot_peer ) * peer_count ); | ||
460 | r += sizeof( ot_peer ) * peer_count; | ||
461 | |||
462 | /* Without the length field */ | ||
463 | *(size_t*)pool_copy = r - sizeof( size_t ); | ||
464 | |||
465 | if( changeset.size + 1 >= changeset.space ) { | ||
466 | size_t new_space = changeset.space ? OT_VECTOR_GROW_RATIO * changeset.space : OT_VECTOR_MIN_MEMBERS; | ||
467 | ot_byte *new_data = realloc( changeset.data, new_space * sizeof( ot_byte *) ); | ||
468 | |||
469 | if( !new_data ) | ||
470 | return free( pool_copy ); | ||
471 | |||
472 | changeset.data = new_data; | ||
473 | changeset.space = new_space; | ||
474 | } | ||
475 | |||
476 | ((ot_byte**)changeset.data)[changeset.size++] = pool_copy; | ||
477 | |||
478 | /* Without the length field */ | ||
479 | changeset_size += r - sizeof( size_t ); | ||
480 | } | ||
481 | |||
482 | /* Import Changeset from an external authority | 440 | /* Import Changeset from an external authority |
483 | format: d4:syncd[..]ee | 441 | format: d4:syncd[..]ee |
484 | [..]: ( 20:01234567890abcdefghij16:XXXXYYYY )+ | 442 | [..]: ( 20:01234567890abcdefghij16:XXXXYYYY )+ |
@@ -523,23 +481,45 @@ int add_changeset_to_tracker( ot_byte *data, size_t len ) { | |||
523 | d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee | 481 | d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee |
524 | */ | 482 | */ |
525 | size_t return_changeset_for_tracker( char **reply ) { | 483 | size_t return_changeset_for_tracker( char **reply ) { |
526 | size_t i, r = 8; | 484 | size_t allocated = 0, i, replysize; |
485 | int bucket; | ||
486 | char *r; | ||
487 | |||
488 | /* Maybe there is time to clean_all_torrents(); */ | ||
489 | |||
490 | /* Determine space needed for whole changeset */ | ||
491 | for( bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket ) { | ||
492 | ot_vector *torrents_list = all_torrents + bucket; | ||
493 | for( i=0; i<torrents_list->size; ++i ) { | ||
494 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + i; | ||
495 | allocated += sizeof( ot_hash ) + sizeof(ot_peer) * torrent->peer_list->changeset.size + 13; | ||
496 | } | ||
497 | } | ||
527 | 498 | ||
528 | clean_all_torrents(); | 499 | /* add "d4:syncd" and "ee" */ |
500 | allocated += 8 + 2; | ||
529 | 501 | ||
530 | if( !( *reply = mmap( NULL, 8 + changeset_size + 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) return 0; | 502 | if( !( r = *reply = mmap( NULL, allocated, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ) ) ) |
503 | return 0; | ||
531 | 504 | ||
532 | memmove( *reply, "d4:syncd", 8 ); | 505 | memmove( r, "d4:syncd", 8 ); r += 8; |
533 | for( i = 0; i < changeset.size; ++i ) { | 506 | for( bucket = 0; bucket < OT_BUCKET_COUNT; ++bucket ) { |
534 | ot_byte *data = ((ot_byte**)changeset.data)[i]; | 507 | ot_vector *torrents_list = all_torrents + bucket; |
535 | memmove( *reply + r, data + sizeof( size_t ), *(size_t*)data ); | 508 | for( i=0; i<torrents_list->size; ++i ) { |
536 | r += *(size_t*)data; | 509 | ot_torrent *torrent = ((ot_torrent*)(torrents_list->data)) + i; |
510 | const size_t byte_count = sizeof(ot_peer) * torrent->peer_list->changeset.size; | ||
511 | *r++ = '2'; *r++ = '0'; *r++ = ':'; | ||
512 | memmove( r, torrent->hash, sizeof( ot_hash ) ); r += sizeof( ot_hash ); | ||
513 | r += sprintf( r, "%zd:", byte_count ); | ||
514 | memmove( r, torrent->peer_list->changeset.data, byte_count ); r += byte_count; | ||
515 | } | ||
537 | } | 516 | } |
517 | *r++ = 'e'; *r++ = 'e'; | ||
538 | 518 | ||
539 | (*reply)[r++] = 'e'; | 519 | replysize = ( r - *reply ); |
540 | (*reply)[r++] = 'e'; | 520 | fix_mmapallocation( *reply, allocated, replysize ); |
541 | 521 | ||
542 | return r; | 522 | return replysize; |
543 | } | 523 | } |
544 | #endif | 524 | #endif |
545 | 525 | ||
@@ -551,6 +531,9 @@ static int clean_single_torrent( ot_torrent *torrent ) { | |||
551 | size_t peers_count = 0, seeds_count; | 531 | size_t peers_count = 0, seeds_count; |
552 | time_t timedout = (int)( NOW - peer_list->base ); | 532 | time_t timedout = (int)( NOW - peer_list->base ); |
553 | int i; | 533 | int i; |
534 | #ifdef WANT_TRACKER_SYNC | ||
535 | char *new_peers; | ||
536 | #endif | ||
554 | 537 | ||
555 | /* Torrent has idled out */ | 538 | /* Torrent has idled out */ |
556 | if( timedout > OT_TORRENT_TIMEOUT ) | 539 | if( timedout > OT_TORRENT_TIMEOUT ) |
@@ -575,10 +558,20 @@ static int clean_single_torrent( ot_torrent *torrent ) { | |||
575 | memmove( peer_list->seed_counts + timedout, peer_list->seed_counts, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); | 558 | memmove( peer_list->seed_counts + timedout, peer_list->seed_counts, sizeof( size_t ) * ( OT_POOLS_COUNT - timedout ) ); |
576 | byte_zero( peer_list->seed_counts, sizeof( size_t ) * timedout ); | 559 | byte_zero( peer_list->seed_counts, sizeof( size_t ) * timedout ); |
577 | 560 | ||
578 | /* Save the block modified within last OT_POOLS_TIMEOUT --- XXX no sync for now | 561 | #ifdef WANT_TRACKER_SYNC |
579 | if( peer_list->peers[1].size ) | 562 | /* Save the block modified within last OT_POOLS_TIMEOUT */ |
580 | add_pool_to_changeset( hash, peer_list->peers[1].data, peer_list->peers[1].size ); | 563 | if( peer_list->peers[1].size && |
581 | */ | 564 | ( new_peers = realloc( peer_list->changeset.data, sizeof( ot_peer ) * peer_list->peers[1].size ) ) ) |
565 | { | ||
566 | memmove( new_peers, peer_list->peers[1].data, peer_list->peers[1].size ); | ||
567 | peer_list->changeset.data = new_peers; | ||
568 | peer_list->changeset.size = sizeof( ot_peer ) * peer_list->peers[1].size; | ||
569 | } else { | ||
570 | free( peer_list->changeset.data ); | ||
571 | |||
572 | memset( &peer_list->changeset, 0, sizeof( ot_vector ) ); | ||
573 | } | ||
574 | #endif | ||
582 | 575 | ||
583 | peers_count = seeds_count = 0; | 576 | peers_count = seeds_count = 0; |
584 | for( i = 0; i < OT_POOLS_COUNT; ++i ) { | 577 | for( i = 0; i < OT_POOLS_COUNT; ++i ) { |
@@ -606,10 +599,6 @@ void clean_all_torrents( void ) { | |||
606 | static int bucket; | 599 | static int bucket; |
607 | ot_time time_now = NOW; | 600 | ot_time time_now = NOW; |
608 | 601 | ||
609 | /* No sync for now | ||
610 | release_changeset(); | ||
611 | */ | ||
612 | |||
613 | /* Search for an uncleaned bucked */ | 602 | /* Search for an uncleaned bucked */ |
614 | while( ( all_torrents_clean[bucket] == time_now ) && ( ++bucket < OT_BUCKET_COUNT ) ); | 603 | while( ( all_torrents_clean[bucket] == time_now ) && ( ++bucket < OT_BUCKET_COUNT ) ); |
615 | if( bucket >= OT_BUCKET_COUNT ) { | 604 | if( bucket >= OT_BUCKET_COUNT ) { |
@@ -869,8 +858,6 @@ int init_logic( const char * const serverdir ) { | |||
869 | 858 | ||
870 | /* Initialize control structures */ | 859 | /* Initialize control structures */ |
871 | byte_zero( all_torrents, sizeof( all_torrents ) ); | 860 | byte_zero( all_torrents, sizeof( all_torrents ) ); |
872 | byte_zero( &changeset, sizeof( changeset ) ); | ||
873 | changeset_size = 0; | ||
874 | 861 | ||
875 | return 0; | 862 | return 0; |
876 | } | 863 | } |
@@ -890,8 +877,6 @@ void deinit_logic( void ) { | |||
890 | } | 877 | } |
891 | byte_zero( all_torrents, sizeof (all_torrents)); | 878 | byte_zero( all_torrents, sizeof (all_torrents)); |
892 | byte_zero( all_torrents_clean, sizeof (all_torrents_clean)); | 879 | byte_zero( all_torrents_clean, sizeof (all_torrents_clean)); |
893 | byte_zero( &changeset, sizeof( changeset ) ); | ||
894 | changeset_size = 0; | ||
895 | } | 880 | } |
896 | 881 | ||
897 | #ifdef WANT_ACCESS_CONTROL | 882 | #ifdef WANT_ACCESS_CONTROL |
diff --git a/trackerlogic.h b/trackerlogic.h index fd8f48a..fc6c884 100644 --- a/trackerlogic.h +++ b/trackerlogic.h | |||
@@ -81,6 +81,9 @@ typedef struct { | |||
81 | size_t down_count; | 81 | size_t down_count; |
82 | size_t seed_counts[ OT_POOLS_COUNT ]; | 82 | size_t seed_counts[ OT_POOLS_COUNT ]; |
83 | ot_vector peers[ OT_POOLS_COUNT ]; | 83 | ot_vector peers[ OT_POOLS_COUNT ]; |
84 | #ifdef WANT_TRACKER_SYNC | ||
85 | ot_vector changeset; | ||
86 | #endif | ||
84 | } ot_peerlist; | 87 | } ot_peerlist; |
85 | 88 | ||
86 | typedef struct { | 89 | typedef struct { |
@@ -97,7 +100,11 @@ void deinit_logic( void ); | |||
97 | 100 | ||
98 | enum { STATS_MRTG, STATS_TOP5, STATS_DMEM, STATS_TCP, STATS_UDP, STATS_SLASH24S, STATS_SLASH24S_OLD, SYNC_IN, SYNC_OUT }; | 101 | enum { STATS_MRTG, STATS_TOP5, STATS_DMEM, STATS_TCP, STATS_UDP, STATS_SLASH24S, STATS_SLASH24S_OLD, SYNC_IN, SYNC_OUT }; |
99 | 102 | ||
103 | #ifdef WANT_TRACKER_SYNC | ||
100 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ); | 104 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ); |
105 | #else | ||
106 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ); | ||
107 | #endif | ||
101 | size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ); | 108 | size_t remove_peer_from_torrent( ot_hash *hash, ot_peer *peer, char *reply, int is_tcp ); |
102 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ); | 109 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, int is_tcp ); |
103 | size_t return_fullscrape_for_tracker( char **reply ); | 110 | size_t return_fullscrape_for_tracker( char **reply ); |