📄 trtrackerservertorrentimpl.java
字号:
protected void
removePeer(
TRTrackerServerPeerImpl peer )
{
removePeer( peer, -1 );
}
protected void
removePeer(
TRTrackerServerPeerImpl peer,
int peer_list_index ) // -1 if not known
{
try{
this_mon.enter();
stats.removeLeft( peer.getAmountLeft());
if ( peer_map.size() != peer_reuse_map.size()){
if ( !map_size_diff_reported ){
map_size_diff_reported = true;
Debug.out( "TRTrackerServerTorrent::removePeer: maps size different ( " + peer_map.size() + "/" + peer_reuse_map.size() +")");
}
}
{
Object o = peer_map.remove( peer.getPeerId());
if ( o == null ){
Debug.out(" TRTrackerServerTorrent::removePeer: peer_map doesn't contain peer");
}
}
if ( peer_list_index == -1 ){
int peer_index = peer_list.indexOf( peer );
if ( peer_index == -1){
Debug.out(" TRTrackerServerTorrent::removePeer: peer_list doesn't contain peer");
}else{
peer_list.set( peer_index, null );
}
}else{
if ( peer_list.get( peer_list_index ) == peer ){
peer_list.set( peer_list_index, null );
}else{
Debug.out(" TRTrackerServerTorrent::removePeer: peer_list doesn't contain peer at index");
}
}
peer_list_hole_count++;
checkForPeerListCompaction( false );
try{
Object o = peer_reuse_map.remove( new String( peer.getIPAsRead(), Constants.BYTE_ENCODING ) + ":" + peer.getPort());
if ( o == null ){
Debug.out(" TRTrackerServerTorrent::removePeer: peer_reuse_map doesn't contain peer");
}
}catch( UnsupportedEncodingException e ){
}
if ( peer.isSeed()){
seed_count--;
}
removed_count++;
}finally{
this_mon.exit();
}
}
public Map
exportAnnounceToMap(
HashMap preprocess_map,
TRTrackerServerPeerImpl requesting_peer, // maybe null for an initial announce from a stopped peer
boolean include_seeds,
int num_want,
long interval,
long min_interval,
boolean no_peer_id,
boolean compact )
{
try{
this_mon.enter();
long now = SystemTime.getCurrentTime();
// we have to force non-caching for nat_warnings responses as they include
// peer-specific data
boolean nat_warning = requesting_peer != null && requesting_peer.getNATStatus() == TRTrackerServerPeerImpl.NAT_CHECK_FAILED;
int total_peers = peer_map.size();
int cache_millis = TRTrackerServerImpl.getAnnounceCachePeriod();
boolean send_peer_ids = TRTrackerServerImpl.getSendPeerIds();
// override if client has explicitly not requested them
if ( no_peer_id || compact ){
send_peer_ids = false;
}
boolean add_to_cache = false;
int max_peers = TRTrackerServerImpl.getMaxPeersToSend();
// num_want < 0 -> not supplied so give them max
if ( num_want < 0 ){
num_want = total_peers;
}
// trim back to max_peers if specified
if ( max_peers > 0 && num_want > max_peers ){
num_want = max_peers;
}
if ( caching_enabled &&
(!nat_warning) &&
preprocess_map.size() == 0 && // don't cache if we've got pre-process stuff to add
cache_millis > 0 &&
num_want >= MIN_CACHE_ENTRY_SIZE &&
total_peers >= TRTrackerServerImpl.getAnnounceCachePeerThreshold()){
// note that we've got to select a cache entry that is somewhat
// relevant to the num_want param (but NOT greater than it)
// remove stuff that's too old
Iterator it = announce_cache.keySet().iterator();
while( it.hasNext() ){
Integer key = (Integer)it.next();
announceCacheEntry entry = (announceCacheEntry)announce_cache.get( key );
if ( now - entry.getTime() > cache_millis ){
it.remove();
}
}
// look for an entry with a reasonable num_want
// e.g. for 100 look between 50 and 100
for (int i=num_want/10;i>num_want/20;i--){
announceCacheEntry entry = (announceCacheEntry)announce_cache.get(new Integer(i));
if( entry != null ){
if ( now - entry.getTime() > cache_millis ){
announce_cache.remove( new Integer(i));
}else{
// make sure this is compatible
if ( entry.getSendPeerIds() == send_peer_ids &&
entry.getCompact() == compact ){
return( entry.getData());
}
}
}
}
add_to_cache = true;
}
List rep_peers = new ArrayList();
// System.out.println( "exportPeersToMap: num_want = " + num_want + ", max = " + max_peers );
// if they want them all simply give them the set
if ( num_want > 0 ){
if ( num_want >= total_peers){
// if they want them all simply give them the set
for (int i=0;i<peer_list.size();i++){
TRTrackerServerPeerImpl peer = (TRTrackerServerPeerImpl)peer_list.get(i);
if ( peer == null ){
}else if ( now > peer.getTimeout()){
// System.out.println( "removing timed out client '" + peer.getString());
removePeer( peer, i );
}else if ( peer.getPort() == 0 ){
// a port of 0 means that the peer definitely can't accept incoming connections
}else if ( include_seeds || !peer.isSeed()){
Map rep_peer = new HashMap(3);
if ( send_peer_ids ){
rep_peer.put( "peer id", peer.getPeerId().getHash());
}
if ( compact ){
byte[] peer_bytes = peer.getIPBytes();
if ( peer_bytes == null ){
continue;
}
rep_peer.put( "ip", peer_bytes );
}else{
rep_peer.put( "ip", peer.getIPAsRead() );
}
rep_peer.put( "port", new Long( peer.getPort()));
rep_peers.add( rep_peer );
}
}
}else{
if ( num_want < total_peers*3 ){
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
for (int i=0;i<limit && added < num_want;i++){
int index = random.nextInt(peer_list_size);
TRTrackerServerPeerImpl peer = (TRTrackerServerPeerImpl)peer_list.get(index);
if ( peer == null ){
}else if ( now > peer.getTimeout()){
removePeer( peer );
peer_removed = true;
}else if ( peer.getPort() == 0 ){
// a port of 0 means that the peer definitely can't accept incoming connections
}else if ( include_seeds || !peer.isSeed()){
boolean bad_nat = peer.isNATStatusBad();
if ( ( bad_nat_loop == 0 && !bad_nat ) ||
( bad_nat_loop == 1 )){
if ( duplicate_peer_checker[index] != duplicate_peer_checker_index ){
duplicate_peer_checker[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 ){
byte[] peer_bytes = peer.getIPBytes();
if ( peer_bytes == null ){
continue;
}
rep_peer.put( "ip", peer_bytes );
}else{
rep_peer.put( "ip", peer.getIPAsRead() );
}
rep_peer.put( "port", new Long( peer.getPort()));
rep_peers.add( rep_peer );
}
}
}
}
}
// System.out.println( "num_want = " + num_want + ", added = " + added + ", bad_nat = " + bad_nat_added );
}finally{
peer_list_compaction_suspended = false;
if ( peer_removed ){
checkForPeerListCompaction( false );
}
}
}else{
// randomly select the peers to return
LinkedList peers = new LinkedList( peer_map.keySet());
int added = 0;
while( added < num_want && peers.size() > 0 ){
String key = (String)peers.remove(random.nextInt(peers.size()));
TRTrackerServerPeerImpl peer = (TRTrackerServerPeerImpl)peer_map.get(key);
if ( now > peer.getTimeout()){
removePeer( peer );
}else if ( peer.getPort() == 0 ){
// a port of 0 means that the peer definitely can't accept incoming connections
}else if ( include_seeds || !peer.isSeed()){
added++;
Map rep_peer = new HashMap(3); // don't use TreeMap as default is "compact"
// so we never actually encode anyway
if ( send_peer_ids ){
rep_peer.put( "peer id", peer.getPeerId().getHash());
}
if ( compact ){
byte[] peer_bytes = peer.getIPBytes();
if ( peer_bytes == null ){
continue;
}
rep_peer.put( "ip", peer_bytes );
}else{
rep_peer.put( "ip", peer.getIPAsRead() );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -