rep_peer.put( "azbiased", "" );
}
if ( network_position != null ){
DHTNetworkPosition peer_pos = peer.getNetworkPosition();
if ( peer_pos != null && network_position.getPositionType() == peer_pos.getPositionType()){
rep_peer.put( "azrtt", new Long( (long)peer_pos.estimateRTT(network_position )));
}
}
}
}
}else{
rep_peer.put( "ip", peer.getIPAsRead() );
}
rep_peer.put( "port", new Long( peer.getTCPPort()));
if ( crypto_level != TRTrackerServerPeer.CRYPTO_NONE ){
rep_peer.put( "crypto_flag", new Long( peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED?1:0));
}
if ( peer.isBiased()){
rep_peers.addFirst( rep_peer );
}else{
rep_peers.addLast( rep_peer );
}
}
}
}else{
int peer_list_size = peer_list.size();
// to avoid returning duplicates when doing the two-loop check
// for nat selection we maintain an array of markers
if ( duplicate_peer_checker.length < peer_list_size ){
duplicate_peer_checker = new byte[peer_list_size*2];
duplicate_peer_checker_index = 1;
}else if ( duplicate_peer_checker.length > (peer_list_size*2)){
duplicate_peer_checker = new byte[(3*peer_list_size)/2];
duplicate_peer_checker_index = 1;
}else{
duplicate_peer_checker_index++;
if ( duplicate_peer_checker_index == 0 ){
Arrays.fill( duplicate_peer_checker, (byte)0);
duplicate_peer_checker_index = 1;
}
}
boolean peer_removed = false;
try{
// got to suspend peer list compaction as we rely on the
// list staying the same size during processing below
peer_list_compaction_suspended = true;
// too costly to randomise as below. use more efficient but slightly less accurate
// approach
// two pass process if bad nat detection enabled
int added = 0;
//int bad_nat_added = 0;
for (int bad_nat_loop=TRTrackerServerNATChecker.getSingleton().isEnabled()?0:1;bad_nat_loop<2;bad_nat_loop++){
int limit = num_want*2; // some entries we find might not be usable
// so in the limit search for more
if ( num_want*3 > total_peers ){
limit++;
}
int biased_peers_count = 0;
if ( biased_peers != null ){ // explicit are additional && explicit_biased_peers == null ){
if ( biased_peers.size() > 1 ){
// juggle things a bit
Object x = biased_peers.remove(0);
biased_peers.add( random.nextInt( biased_peers.size() + 1 ), x);
}
biased_peers_count = Math.min( min_biased_peers, biased_peers.size());
}
for (int i=0;i<limit && added < num_want;i++){
int peer_index;
TRTrackerServerPeerImpl peer;
// deal with bias up front
if ( bad_nat_loop == 1 && i < biased_peers_count ){
peer = (TRTrackerServerPeerImpl)biased_peers.get(i);
peer_index = -1; // don't know actual index and don't need to as biased peers processed separately
}else{
peer_index = random.nextInt(peer_list_size);
peer = (TRTrackerServerPeerImpl)peer_list.get(peer_index);
if ( peer == null || peer.isBiased()){
continue;
}
}
if ( now > peer.getTimeout()){
removePeer( peer, TRTrackerServerTorrentPeerListener.ET_TIMEOUT, null );
peer_removed = true;
}else if ( requesting_peer == peer || peer.getTCPPort() == 0 ){
// a port of 0 means that the peer definitely can't accept incoming connections
}else if ( crypto_level == TRTrackerServerPeer.CRYPTO_NONE && peer.getCryptoLevel() == TRTrackerServerPeer.CRYPTO_REQUIRED ){
// don't return "crypto required" peers to those that can't correctly connect to them
}else if ( remove_ips != null && remove_ips.contains( new String( peer.getIP()))){
// skippy skippy
}else if ( include_seeds || !peer.isSeed()){
boolean bad_nat = peer.isNATStatusBad();
if ( ( bad_nat_loop == 0 && !bad_nat ) ||
( bad_nat_loop == 1 )){
if ( peer_index == -1 || duplicate_peer_checker[peer_index] != duplicate_peer_checker_index ){
if ( peer_index != -1 ){
duplicate_peer_checker[peer_index] = duplicate_peer_checker_index;
}
//if ( bad_nat ){
//
// bad_nat_added++;
//}
added++;
Map rep_peer = new HashMap(3);
if ( send_peer_ids ){
rep_peer.put( "peer id", peer.getPeerId().getHash());
}
if ( compact_mode != COMPACT_MODE_NONE ){
byte[] peer_bytes = peer.getIPAddressBytes();
if ( peer_bytes == null ){
continue;
}
rep_peer.put( "ip", peer_bytes );
if ( compact_mode >= COMPACT_MODE_AZ ){
rep_peer.put( "azver", new Long( peer.getAZVer()));
rep_peer.put( "azudp", new Long( peer.getUDPPort()));
if ( peer.isSeed()){
rep_peer.put( "azhttp", new Long( peer.getHTTPPort()));
}
if ( compact_mode >= COMPACT_MODE_XML ){
rep_peer.put( "ip", peer.getIPAsRead() );
}else{
rep_peer.put( "azup", new Long( peer.getUpSpeed()));
if ( peer.isBiased()){
rep_peer.put( "azbiased", "" );
}
if ( network_position != null ){
DHTNetworkPosition peer_pos = peer.getNetworkPosition();
if ( peer_pos != null && network_position.getPositionType() == peer_pos.getPositionType()){
rep_peer.put( "azrtt", new Long( (long)peer_pos.estimateRTT(network_position )));
}
}
}
}
}else{