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 | ||