diff options
Diffstat (limited to 'trackerlogic.c')
| -rw-r--r-- | trackerlogic.c | 110 |
1 files changed, 58 insertions, 52 deletions
diff --git a/trackerlogic.c b/trackerlogic.c index d2d279e..5bda0df 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -19,26 +19,12 @@ | |||
| 19 | #include "scan.h" | 19 | #include "scan.h" |
| 20 | #include "byte.h" | 20 | #include "byte.h" |
| 21 | 21 | ||
| 22 | #if defined( WANT_CLOSED_TRACKER ) || defined( WANT_BLACKLIST ) | ||
| 23 | #include <sys/stat.h> | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /* GLOBAL VARIABLES */ | 22 | /* GLOBAL VARIABLES */ |
| 27 | static ot_vector all_torrents[256]; | 23 | static ot_vector all_torrents[256]; |
| 28 | static ot_vector changeset; | 24 | static ot_vector changeset; |
| 29 | size_t changeset_size = 0; | 25 | size_t changeset_size = 0; |
| 30 | time_t last_clean_time = 0; | 26 | time_t last_clean_time = 0; |
| 31 | 27 | ||
| 32 | #ifdef WANT_CLOSED_TRACKER | ||
| 33 | int g_closedtracker = 1; | ||
| 34 | static ot_torrent* const OT_TORRENT_NOT_ON_WHITELIST = (ot_torrent*)1; | ||
| 35 | #endif | ||
| 36 | |||
| 37 | #ifdef WANT_BLACKLIST | ||
| 38 | int g_check_blacklist = 1; | ||
| 39 | static ot_torrent* const OT_TORRENT_ON_BLACKLIST = (ot_torrent*)2; | ||
| 40 | #endif | ||
| 41 | |||
| 42 | /* Converter function from memory to human readable hex strings | 28 | /* Converter function from memory to human readable hex strings |
| 43 | - definitely not thread safe!!! | 29 | - definitely not thread safe!!! |
| 44 | */ | 30 | */ |
| @@ -162,25 +148,12 @@ static int vector_remove_torrent( ot_vector *vector, ot_hash *hash ) { | |||
| 162 | return 1; | 148 | return 1; |
| 163 | } | 149 | } |
| 164 | 150 | ||
| 165 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | 151 | ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer, int from_changeset ) { |
| 166 | int exactmatch; | 152 | int exactmatch; |
| 167 | ot_torrent *torrent; | 153 | ot_torrent *torrent; |
| 168 | ot_peer *peer_dest; | 154 | ot_peer *peer_dest; |
| 169 | ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool; | 155 | ot_vector *torrents_list = &all_torrents[*hash[0]], *peer_pool; |
| 170 | #if defined( WANT_CLOSED_TRACKER ) || defined( WANT_BLACKLIST ) | 156 | int base_pool = 0; |
| 171 | struct stat dummy_sb; | ||
| 172 | char *fn = to_hex( (ot_byte*)hash ); | ||
| 173 | #endif | ||
| 174 | |||
| 175 | #ifdef WANT_CLOSED_TRACKER | ||
| 176 | if( g_closedtracker && stat( fn, &dummy_sb ) ) | ||
| 177 | return OT_TORRENT_NOT_ON_WHITELIST; | ||
| 178 | #endif | ||
| 179 | |||
| 180 | #ifdef WANT_BLACKLIST | ||
| 181 | if( g_check_blacklist && !stat( fn - 1, &dummy_sb ) ) | ||
| 182 | return OT_TORRENT_ON_BLACKLIST; | ||
| 183 | #endif | ||
| 184 | 157 | ||
| 185 | torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); | 158 | torrent = vector_find_or_insert( torrents_list, (void*)hash, sizeof( ot_torrent ), OT_HASH_COMPARE_SIZE, &exactmatch ); |
| 186 | if( !torrent ) return NULL; | 159 | if( !torrent ) return NULL; |
| @@ -202,7 +175,16 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | |||
| 202 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) | 175 | if( ( OT_FLAG( peer ) & ( PEER_FLAG_COMPLETED | PEER_FLAG_SEEDING ) ) == PEER_FLAG_COMPLETED ) |
| 203 | OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; | 176 | OT_FLAG( peer ) ^= PEER_FLAG_COMPLETED; |
| 204 | 177 | ||
| 205 | peer_pool = &torrent->peer_list->peers[0]; | 178 | if( from_changeset ) { |
| 179 | /* Check, whether peer already is in current pool, do nothing if so */ | ||
| 180 | peer_pool = &torrent->peer_list->peers[0]; | ||
| 181 | binary_search( peer, peer_pool->data, peer_pool->size, sizeof(ot_peer), OT_PEER_COMPARE_SIZE, &exactmatch ); | ||
| 182 | if( exactmatch ) | ||
| 183 | return torrent; | ||
| 184 | base_pool = 1; | ||
| 185 | } | ||
| 186 | |||
| 187 | peer_pool = &torrent->peer_list->peers[ base_pool ]; | ||
| 206 | peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); | 188 | peer_dest = vector_find_or_insert( peer_pool, (void*)peer, sizeof( ot_peer ), OT_PEER_COMPARE_SIZE, &exactmatch ); |
| 207 | 189 | ||
| 208 | /* If we hadn't had a match in current pool, create peer there and | 190 | /* If we hadn't had a match in current pool, create peer there and |
| @@ -215,9 +197,9 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | |||
| 215 | torrent->peer_list->downloaded++; | 197 | torrent->peer_list->downloaded++; |
| 216 | 198 | ||
| 217 | if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) | 199 | if( OT_FLAG(peer) & PEER_FLAG_SEEDING ) |
| 218 | torrent->peer_list->seed_count[0]++; | 200 | torrent->peer_list->seed_count[ base_pool ]++; |
| 219 | 201 | ||
| 220 | for( i=1; i<OT_POOLS_COUNT; ++i ) { | 202 | for( i= base_pool + 1; i<OT_POOLS_COUNT; ++i ) { |
| 221 | switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) { | 203 | switch( vector_remove_peer( &torrent->peer_list->peers[i], peer, 0 ) ) { |
| 222 | case 0: continue; | 204 | case 0: continue; |
| 223 | case 2: torrent->peer_list->seed_count[i]--; | 205 | case 2: torrent->peer_list->seed_count[i]--; |
| @@ -226,9 +208,9 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | |||
| 226 | } | 208 | } |
| 227 | } else { | 209 | } else { |
| 228 | if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) | 210 | if( (OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && !(OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) |
| 229 | torrent->peer_list->seed_count[0]--; | 211 | torrent->peer_list->seed_count[ base_pool ]--; |
| 230 | if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) | 212 | if( !(OT_FLAG(peer_dest) & PEER_FLAG_SEEDING ) && (OT_FLAG(peer) & PEER_FLAG_SEEDING ) ) |
| 231 | torrent->peer_list->seed_count[0]++; | 213 | torrent->peer_list->seed_count[ base_pool ]++; |
| 232 | if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) ) | 214 | if( !(OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) && (OT_FLAG( peer ) & PEER_FLAG_COMPLETED ) ) |
| 233 | torrent->peer_list->downloaded++; | 215 | torrent->peer_list->downloaded++; |
| 234 | if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) | 216 | if( OT_FLAG( peer_dest ) & PEER_FLAG_COMPLETED ) |
| @@ -250,22 +232,6 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply | |||
| 250 | char *r = reply; | 232 | char *r = reply; |
| 251 | size_t peer_count, seed_count, index; | 233 | size_t peer_count, seed_count, index; |
| 252 | 234 | ||
| 253 | #ifdef WANT_CLOSED_TRACKER | ||
| 254 | if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) { | ||
| 255 | const char * const notvalid = "d14:failure reason43:This torrent is not served by this tracker.e"; | ||
| 256 | memmove( reply, notvalid, sizeof(notvalid)); | ||
| 257 | return sizeof(notvalid); | ||
| 258 | } | ||
| 259 | #endif | ||
| 260 | |||
| 261 | #ifdef WANT_BLACKLIST | ||
| 262 | if( torrent == OT_TORRENT_ON_BLACKLIST ) { | ||
| 263 | const char * const blacklisted = "d14:failure reason29:This torrent is black listed.e"; | ||
| 264 | memmove( reply, blacklisted, sizeof(blacklisted)); | ||
| 265 | return sizeof(blacklisted); | ||
| 266 | } | ||
| 267 | #endif | ||
| 268 | |||
| 269 | for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) { | 235 | for( peer_count = seed_count = index = 0; index < OT_POOLS_COUNT; ++index ) { |
| 270 | peer_count += torrent->peer_list->peers[index].size; | 236 | peer_count += torrent->peer_list->peers[index].size; |
| 271 | seed_count += torrent->peer_list->seed_count[index]; | 237 | seed_count += torrent->peer_list->seed_count[index]; |
| @@ -473,8 +439,48 @@ static void add_pool_to_changeset( ot_hash *hash, ot_peer *peers, size_t peer_co | |||
| 473 | changeset_size += r - sizeof( size_t ); | 439 | changeset_size += r - sizeof( size_t ); |
| 474 | } | 440 | } |
| 475 | 441 | ||
| 442 | /* Import Changeset from an external authority | ||
| 443 | format: d4:syncd[..]ee | ||
| 444 | [..]: ( 20:01234567890abcdefghij16:XXXXYYYY )+ | ||
| 445 | */ | ||
| 446 | int add_changeset_to_tracker( ot_byte *data, size_t len ) { | ||
| 447 | ot_hash *hash; | ||
| 448 | ot_byte *end = data + len; | ||
| 449 | size_t peer_count; | ||
| 450 | |||
| 451 | /* We do know, that the string is \n terminated, so it cant | ||
| 452 | overflow */ | ||
| 453 | if( byte_diff( data, 8, "d4:syncd" ) ) return -1; | ||
| 454 | data += 8; | ||
| 455 | |||
| 456 | while( 1 ) { | ||
| 457 | if( byte_diff( data, 3, "20:" ) ) { | ||
| 458 | if( byte_diff( data, 2, "ee" ) ) | ||
| 459 | return -1; | ||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | data += 3; | ||
| 463 | hash = (ot_hash*)data; | ||
| 464 | data += sizeof( ot_hash ); | ||
| 465 | |||
| 466 | /* Scan string length indicator */ | ||
| 467 | data += ( len = scan_ulong( (char*)data, &peer_count ) ); | ||
| 468 | |||
| 469 | /* If no long was scanned, it is not divisible by 8, it is not | ||
| 470 | followed by a colon or claims to need to much memory, we fail */ | ||
| 471 | if( !len || !peer_count || ( peer_count & 7 ) || ( *data++ != ':' ) || ( data + peer_count > end ) ) | ||
| 472 | return -1; | ||
| 473 | |||
| 474 | while( peer_count > 0 ) { | ||
| 475 | add_peer_to_torrent( hash, (ot_peer*)data, 1 ); | ||
| 476 | data += 8; peer_count -= 8; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | return 0; | ||
| 480 | } | ||
| 481 | |||
| 476 | /* Proposed output format | 482 | /* Proposed output format |
| 477 | d4:syncd20:<info_hash>8*N:(xxxxyy)*Nee | 483 | d4:syncd20:<info_hash>8*N:(xxxxyyyy)*Nee |
| 478 | */ | 484 | */ |
| 479 | size_t return_changeset_for_tracker( char **reply ) { | 485 | size_t return_changeset_for_tracker( char **reply ) { |
| 480 | size_t i, r = 8; | 486 | size_t i, r = 8; |
