diff options
| -rw-r--r-- | trackerlogic.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/trackerlogic.c b/trackerlogic.c index b3aacc0..e4ea0ea 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -229,7 +229,6 @@ ot_torrent *add_peer_to_torrent( ot_hash *hash, ot_peer *peer ) { | |||
| 229 | size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) { | 229 | size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char *reply ) { |
| 230 | char *r = reply; | 230 | char *r = reply; |
| 231 | unsigned int peer_count, seed_count, index; | 231 | unsigned int peer_count, seed_count, index; |
| 232 | int pool_offset = -1, pool_index = 0, wert = -1; | ||
| 233 | 232 | ||
| 234 | #ifdef WANT_CLOSED_TRACKER | 233 | #ifdef WANT_CLOSED_TRACKER |
| 235 | if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) { | 234 | if( torrent == OT_TORRENT_NOT_ON_WHITELIST ) { |
| @@ -254,19 +253,36 @@ size_t return_peers_for_torrent( ot_torrent *torrent, unsigned int amount, char | |||
| 254 | if( peer_count < amount ) amount = peer_count; | 253 | if( peer_count < amount ) amount = peer_count; |
| 255 | 254 | ||
| 256 | r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali600e5:peers%i:", seed_count, peer_count-seed_count, 6*amount ); | 255 | r += sprintf( r, "d8:completei%ie10:incompletei%ie8:intervali600e5:peers%i:", seed_count, peer_count-seed_count, 6*amount ); |
| 257 | for( index = 0; index < amount; ++index ) { | 256 | if( amount ) { |
| 258 | double step = 1.8*((double)( peer_count - wert - 1 ))/((double)( amount - index )); | 257 | unsigned int pool_offset, pool_index = 0;; |
| 259 | int off = random() % (int)step; | 258 | unsigned int shifted_pc = peer_count; |
| 260 | off = 1 + ( off % ( peer_count - wert - 1 )); | 259 | unsigned int shifted_step = 0; |
| 261 | wert += off; pool_offset += off; | 260 | unsigned int shift = 0; |
| 262 | 261 | ||
| 263 | while( pool_offset >= torrent->peer_list->peers[pool_index].size ) { | 262 | /* Make fixpoint arithmetic as exact as possible */ |
| 264 | pool_offset -= torrent->peer_list->peers[pool_index].size; | 263 | #define MAXPRECBIT (1<<(8*sizeof(int)-3)) |
| 265 | pool_index++; | 264 | while( !(shifted_pc & MAXPRECBIT ) ) { shifted_pc <<= 1; shift++; } |
| 266 | } | 265 | shifted_step = shifted_pc/amount; |
| 266 | #undef MAXPRECBIT | ||
| 267 | |||
| 268 | /* Initialize somewhere in the middle of peers so that | ||
| 269 | fixpoint's aliasing doesn't alway miss the same peers */ | ||
| 270 | pool_offset = random() % peer_count; | ||
| 271 | |||
| 272 | for( index = 0; index < amount; ++index ) { | ||
| 273 | /* This is the aliased, non shifted range, next value may fall into */ | ||
| 274 | unsigned int diff = ( ( ( index + 1 ) * shifted_step ) >> shift ) - | ||
| 275 | ( ( index * shifted_step ) >> shift ); | ||
| 276 | pool_offset += 1 + random() % diff; | ||
| 277 | |||
| 278 | while( pool_offset >= torrent->peer_list->peers[pool_index].size ) { | ||
| 279 | pool_offset -= torrent->peer_list->peers[pool_index].size; | ||
| 280 | pool_index = ( pool_index + 1 ) % OT_POOLS_COUNT; | ||
| 281 | } | ||
| 267 | 282 | ||
| 268 | memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 ); | 283 | memmove( r, ((ot_peer*)torrent->peer_list->peers[pool_index].data) + pool_offset, 6 ); |
| 269 | r += 6; | 284 | r += 6; |
| 285 | } | ||
| 270 | } | 286 | } |
| 271 | *r++ = 'e'; | 287 | *r++ = 'e'; |
| 272 | 288 | ||
