mirror of
				git://erdgeist.org/opentracker
				synced 2025-11-03 19:33:23 +08:00 
			
		
		
		
	Return peer from both address families on announce
This commit is contained in:
		
							parent
							
								
									880d5145a0
								
							
						
					
					
						commit
						d9a5f04675
					
				
							
								
								
									
										118
									
								
								trackerlogic.c
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								trackerlogic.c
									
									
									
									
									
								
							@ -276,6 +276,94 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee
 | 
				
			|||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t return_peers_for_torrent_udp( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply ) {
 | 
				
			||||||
 | 
					  char                *r = reply;
 | 
				
			||||||
 | 
					  size_t       peer_size = peer_size_from_peer6(&ws->peer);
 | 
				
			||||||
 | 
					  ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if( amount > peer_list->peer_count )
 | 
				
			||||||
 | 
					    amount = peer_list->peer_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM );
 | 
				
			||||||
 | 
					  *(uint32_t*)(r+4) = htonl( peer_list->peer_count - peer_list->seed_count );
 | 
				
			||||||
 | 
					  *(uint32_t*)(r+8) = htonl( peer_list->seed_count );
 | 
				
			||||||
 | 
					  r += 12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if( amount ) {
 | 
				
			||||||
 | 
					    if( amount == peer_list->peer_count )
 | 
				
			||||||
 | 
					      r += return_peers_all( peer_list, peer_size, r );
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      r += return_peers_selection( ws, peer_list, peer_size, amount, r );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return r - reply;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static size_t return_peers_for_torrent_tcp( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply ) {
 | 
				
			||||||
 | 
					  char   *r = reply;
 | 
				
			||||||
 | 
					  int     erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM;
 | 
				
			||||||
 | 
					  size_t  seed_count = torrent->peer_list6->seed_count + torrent->peer_list4->seed_count;
 | 
				
			||||||
 | 
					  size_t  down_count = torrent->peer_list6->down_count + torrent->peer_list4->down_count;
 | 
				
			||||||
 | 
					  size_t  peer_count = torrent->peer_list6->peer_count + torrent->peer_list4->peer_count - seed_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Simple case: amount of peers in both lists is less than requested, here we return all results */
 | 
				
			||||||
 | 
					  size_t  amount_v4 = torrent->peer_list4->peer_count;
 | 
				
			||||||
 | 
					  size_t  amount_v6 = torrent->peer_list6->peer_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Complex case: both lists have more than enough entries and we need to split between v4 and v6 clients */
 | 
				
			||||||
 | 
					  if( amount_v4 + amount_v6 > amount ) {
 | 
				
			||||||
 | 
					    size_t amount_left, percent_v6 = 0, percent_v4 = 0, left_v6, left_v4;
 | 
				
			||||||
 | 
					    const size_t SCALE = 1024;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* If possible, fill at least a quarter of peer from each family */
 | 
				
			||||||
 | 
					    if( amount / 4 <= amount_v4 )
 | 
				
			||||||
 | 
					        amount_v4 = amount / 4;
 | 
				
			||||||
 | 
					    if( amount / 4 <= amount_v6 )
 | 
				
			||||||
 | 
					        amount_v6 = amount / 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Fill the rest according to which family's pool provides more peers */
 | 
				
			||||||
 | 
					    amount_left = amount - (amount_v4 + amount_v6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    left_v4     = torrent->peer_list4->peer_count - amount_v4;
 | 
				
			||||||
 | 
					    left_v6     = torrent->peer_list6->peer_count - amount_v6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if( left_v4 + left_v6 ) {
 | 
				
			||||||
 | 
					      percent_v4  = (SCALE * left_v4) / (left_v4 + left_v6);
 | 
				
			||||||
 | 
					      percent_v6  = (SCALE * left_v6) / (left_v4 + left_v6);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    amount_v4  += (amount_left * percent_v4) / SCALE;
 | 
				
			||||||
 | 
					    amount_v6  += (amount_left * percent_v6) / SCALE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Integer division rounding can leave out a peer */
 | 
				
			||||||
 | 
					    if( amount_v4 + amount_v6 < amount && amount_v6 < torrent->peer_list6->peer_count )
 | 
				
			||||||
 | 
					      ++amount_v6;
 | 
				
			||||||
 | 
					    if( amount_v4 + amount_v6 < amount && amount_v4 < torrent->peer_list4->peer_count )
 | 
				
			||||||
 | 
					      ++amount_v4;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie", seed_count, down_count, peer_count, erval, erval/2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if( amount_v4 ) {
 | 
				
			||||||
 | 
					    r += sprintf( r, PEERS_BENCODED4 "%zd:", OT_PEER_COMPARE_SIZE4 * amount_v4);
 | 
				
			||||||
 | 
					    if( amount_v4 == torrent->peer_list4->peer_count )
 | 
				
			||||||
 | 
					      r += return_peers_all( torrent->peer_list4, OT_PEER_SIZE4, r );
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      r += return_peers_selection( ws, torrent->peer_list4, OT_PEER_SIZE4, amount_v4, r );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if( amount_v6 ) {
 | 
				
			||||||
 | 
					    r += sprintf( r, PEERS_BENCODED6 "%zd:", OT_PEER_COMPARE_SIZE6 * amount_v6);
 | 
				
			||||||
 | 
					    if( amount_v6 == torrent->peer_list6->peer_count )
 | 
				
			||||||
 | 
					      r += return_peers_all( torrent->peer_list6, OT_PEER_SIZE6, r );
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      r += return_peers_selection( ws, torrent->peer_list6, OT_PEER_SIZE6, amount_v6, r );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *r++ = 'e';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return r - reply;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Compiles a list of random peers for a torrent
 | 
					/* Compiles a list of random peers for a torrent
 | 
				
			||||||
   * Reply must have enough space to hold:
 | 
					   * Reply must have enough space to hold:
 | 
				
			||||||
   * 92 + 6 * amount bytes for TCP/IPv4
 | 
					   * 92 + 6 * amount bytes for TCP/IPv4
 | 
				
			||||||
@ -285,35 +373,7 @@ static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *pee
 | 
				
			|||||||
   * Does not yet check not to return self
 | 
					   * Does not yet check not to return self
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) {
 | 
					size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) {
 | 
				
			||||||
  size_t       peer_size = peer_size_from_peer6(&ws->peer);
 | 
					  return proto == FLAG_TCP ? return_peers_for_torrent_tcp(ws, torrent, amount, reply) : return_peers_for_torrent_udp(ws, torrent, amount, reply);
 | 
				
			||||||
  ot_peerlist *peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4;
 | 
					 | 
				
			||||||
  char        *r = reply;
 | 
					 | 
				
			||||||
  size_t      compare_size = OT_PEER_COMPARE_SIZE_FROM_PEER_SIZE(peer_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if( amount > peer_list->peer_count )
 | 
					 | 
				
			||||||
    amount = peer_list->peer_count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if( proto == FLAG_TCP ) {
 | 
					 | 
				
			||||||
    int erval = OT_CLIENT_REQUEST_INTERVAL_RANDOM;
 | 
					 | 
				
			||||||
    r += sprintf( r, "d8:completei%zde10:downloadedi%zde10:incompletei%zde8:intervali%ie12:min intervali%ie%s%zd:", peer_list->seed_count, peer_list->down_count, peer_list->peer_count-peer_list->seed_count, erval, erval/2, peer_size == OT_PEER_SIZE6 ? PEERS_BENCODED6 : PEERS_BENCODED4, compare_size * amount );
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    *(uint32_t*)(r+0) = htonl( OT_CLIENT_REQUEST_INTERVAL_RANDOM );
 | 
					 | 
				
			||||||
    *(uint32_t*)(r+4) = htonl( peer_list->peer_count - peer_list->seed_count );
 | 
					 | 
				
			||||||
    *(uint32_t*)(r+8) = htonl( peer_list->seed_count );
 | 
					 | 
				
			||||||
    r += 12;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if( amount ) {
 | 
					 | 
				
			||||||
    if( amount == peer_list->peer_count )
 | 
					 | 
				
			||||||
      r += return_peers_all( peer_list, peer_size, r );
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
      r += return_peers_selection( ws, peer_list, peer_size, amount, r );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if( proto == FLAG_TCP )
 | 
					 | 
				
			||||||
    *r++ = 'e';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return r - reply;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Fetches scrape info for a specific torrent */
 | 
					/* Fetches scrape info for a specific torrent */
 | 
				
			||||||
 | 
				
			|||||||
@ -82,7 +82,7 @@ typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA, FLAG_SELFPIPE } PROTO_FLAG;
 | 
				
			|||||||
#define OT_PEER_SIZE6 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE6))
 | 
					#define OT_PEER_SIZE6 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE6))
 | 
				
			||||||
#define OT_PEER_SIZE4 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE4))
 | 
					#define OT_PEER_SIZE4 ((OT_TIME_SIZE)+(OT_FLAG_SIZE)+(OT_PEER_COMPARE_SIZE4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef uint8_t ot_peer[1]; /* Generic pointer to a v6 or v4 peer */
 | 
					typedef uint8_t ot_peer; /* Generic pointer to a v6 or v4 peer */
 | 
				
			||||||
typedef uint8_t ot_peer6[OT_PEER_SIZE6];
 | 
					typedef uint8_t ot_peer6[OT_PEER_SIZE6];
 | 
				
			||||||
typedef uint8_t ot_peer4[OT_PEER_SIZE4];
 | 
					typedef uint8_t ot_peer4[OT_PEER_SIZE4];
 | 
				
			||||||
static const uint8_t PEER_FLAG_SEEDING   = 0x80;
 | 
					static const uint8_t PEER_FLAG_SEEDING   = 0x80;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user