package org.gudy.azureus2.core3.peer.impl.control;
///*
// * Created by Olivier Chalouhi
// * Modified Apr 13, 2004 by Alon Rohter
// * Heavily modified Sep 2005 by Joseph Bridgewater
// * Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
// *
// * This program is free software; you can redistribute it and/or
// * modify it under the terms of the GNU General Public License
// * as published by the Free Software Foundation; either version 2
// * of the License, or (at your option) any later version.
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// * You should have received a copy of the GNU General Public License
// * along with this program; if not, write to the Free Software
// * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// *
// * AELITIS, SAS au capital de 46,603.30 euros
// * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
// */
//
//package org.gudy.azureus2.core3.peer.impl.control;
//
//
//import java.net.Inet6Address;
//import java.net.InetAddress;
//import java.net.InetSocketAddress;
//import java.net.UnknownHostException;
//import java.nio.ByteBuffer;
//import java.util.*;
//
//import org.gudy.azureus2.core3.config.COConfigurationManager;
//import org.gudy.azureus2.core3.config.ParameterListener;
//import org.gudy.azureus2.core3.disk.*;
//import org.gudy.azureus2.core3.ipfilter.*;
//import org.gudy.azureus2.core3.logging.*;
//import org.gudy.azureus2.core3.peer.*;
//import org.gudy.azureus2.core3.peer.impl.*;
//import org.gudy.azureus2.core3.peer.util.PeerIdentityDataID;
//import org.gudy.azureus2.core3.peer.util.PeerIdentityManager;
//import org.gudy.azureus2.core3.peer.util.PeerUtils;
//import org.gudy.azureus2.core3.torrent.TOTorrentException;
//import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncer;
//import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponse;
//import org.gudy.azureus2.core3.tracker.client.TRTrackerAnnouncerResponsePeer;
//import org.gudy.azureus2.core3.tracker.client.TRTrackerScraperResponse;
//import org.gudy.azureus2.core3.util.*;
//import org.gudy.azureus2.plugins.download.DownloadAnnounceResultPeer;
//import org.gudy.azureus2.plugins.peers.Peer;
//import org.gudy.azureus2.plugins.peers.PeerDescriptor;
//
////import com.aelitis.azureus.core.networkmanager.LimitedRateGroup;
////import com.aelitis.azureus.core.networkmanager.admin.NetworkAdmin;
//import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPConnectionManager;
//import com.aelitis.azureus.core.networkmanager.impl.tcp.TCPNetworkManager;
//import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
//import com.aelitis.azureus.core.peermanager.control.PeerControlInstance;
//import com.aelitis.azureus.core.peermanager.control.PeerControlScheduler;
//import com.aelitis.azureus.core.peermanager.control.PeerControlSchedulerFactory;
//import com.aelitis.azureus.core.peermanager.nat.PeerNATInitiator;
//import com.aelitis.azureus.core.peermanager.nat.PeerNATTraversalAdapter;
//import com.aelitis.azureus.core.peermanager.nat.PeerNATTraverser;
//import com.aelitis.azureus.core.peermanager.peerdb.*;
//import com.aelitis.azureus.core.peermanager.piecepicker.PiecePicker;
//import com.aelitis.azureus.core.peermanager.piecepicker.PiecePickerFactory;
//import com.aelitis.azureus.core.peermanager.unchoker.Unchoker;
//import com.aelitis.azureus.core.peermanager.unchoker.UnchokerFactory;
//import com.aelitis.azureus.core.peermanager.unchoker.UnchokerUtil;
//import com.aelitis.azureus.core.peermanager.uploadslots.UploadHelper;
//import com.aelitis.azureus.core.peermanager.uploadslots.UploadSlotManager;
//import com.aelitis.azureus.core.util.FeatureAvailability;
//import com.aelitis.azureus.core.util.bloom.BloomFilter;
//import com.aelitis.azureus.core.util.bloom.BloomFilterFactory;
//
///**
// * manages all peer transports for a torrent
// *
// * @author MjrTom
// * 2005/Oct/08: Numerous changes for new piece-picking. Also
// * a few optimizations and multi-thread cleanups
// * 2006/Jan/02: refactoring piece picking related code
// */
//
//@SuppressWarnings("serial")
//public class
//PEPeerControlImpl
////extends LogRelation
//implements PEPeerControl, ParameterListener, DiskManagerWriteRequestListener, PeerControlInstance,
//// PeerNATInitiator,
//DiskManagerCheckRequestListener
//// , IPFilterListener
//{
//// private static final LogIDs LOGID = LogIDs.PEER;
//
// private static final int WARNINGS_LIMIT = 2;
//
// private static final int CHECK_REASON_DOWNLOADED = 1;
// private static final int CHECK_REASON_COMPLETE = 2;
// private static final int CHECK_REASON_SCAN = 3;
// private static final int CHECK_REASON_SEEDING_CHECK = 4;
// private static final int CHECK_REASON_BAD_PIECE_CHECK = 5;
//
// private static final int SEED_CHECK_WAIT_MARKER = 65526;
//
// // config
//
// private static boolean disconnect_seeds_when_seeding;
// private static boolean enable_seeding_piece_rechecks;
// private static int stalled_piece_timeout;
// private static boolean fast_unchoke_new_peers;
// private static float ban_peer_discard_ratio;
// private static int ban_peer_discard_min_kb;
// private static boolean udp_fallback_for_failed_connection;
// private static boolean udp_fallback_for_dropped_connection;
// private static boolean udp_probe_enabled;
// private static boolean hide_a_piece;
// private static boolean prefer_udp_default;
//
// static{
//
// COConfigurationManager.addAndFireParameterListeners(
// new String[]{
// "Disconnect Seed",
// "Seeding Piece Check Recheck Enable",
// "peercontrol.stalled.piece.write.timeout",
// "Peer.Fast.Initial.Unchoke.Enabled",
// "Ip Filter Ban Discard Ratio",
// "Ip Filter Ban Discard Min KB",
// "peercontrol.udp.fallback.connect.fail",
// "peercontrol.udp.fallback.connect.drop",
// "peercontrol.udp.probe.enable",
// "peercontrol.hide.piece",
// "peercontrol.prefer.udp",
// },
// new ParameterListener()
// {
// public void
// parameterChanged(
// String name )
// {
// disconnect_seeds_when_seeding = COConfigurationManager.getBooleanParameter("Disconnect Seed");
// enable_seeding_piece_rechecks = COConfigurationManager.getBooleanParameter("Seeding Piece Check Recheck Enable");
// stalled_piece_timeout = COConfigurationManager.getIntParameter( "peercontrol.stalled.piece.write.timeout", 60*1000 );
// fast_unchoke_new_peers = COConfigurationManager.getBooleanParameter( "Peer.Fast.Initial.Unchoke.Enabled" );
// ban_peer_discard_ratio = COConfigurationManager.getFloatParameter( "Ip Filter Ban Discard Ratio" );
// ban_peer_discard_min_kb = COConfigurationManager.getIntParameter( "Ip Filter Ban Discard Min KB" );
// udp_fallback_for_failed_connection = COConfigurationManager.getBooleanParameter( "peercontrol.udp.fallback.connect.fail" );
// udp_fallback_for_dropped_connection = COConfigurationManager.getBooleanParameter( "peercontrol.udp.fallback.connect.drop" );
// udp_probe_enabled = COConfigurationManager.getBooleanParameter( "peercontrol.udp.probe.enable" );
// hide_a_piece = COConfigurationManager.getBooleanParameter( "peercontrol.hide.piece" );
//
// if ( hide_a_piece ){
//
// disconnect_seeds_when_seeding = false;
// }
//
// prefer_udp_default = COConfigurationManager.getBooleanParameter( "peercontrol.prefer.udp" );
// }
// });
// }
//
// private static IpFilter ip_filter = IpFilterManagerFactory.getSingleton().getIPFilter();
//
// private volatile boolean is_running = false;
// private volatile boolean is_destroyed = false;
//
// private volatile ArrayList<PEPeer> peer_transports_cow = new ArrayList<PEPeer>(); // Copy on write!
// private final AEMonitor peer_transports_mon = new AEMonitor( "PEPeerControl:PT");
//
// protected final PEPeerManagerAdapter adapter;
// private final DiskManager disk_mgr;
// private final DiskManagerPiece[] dm_pieces;
//
// private final PiecePicker piecePicker;
// private long lastNeededUndonePieceChange;
//
// /** literally seeding as in 100% torrent complete */
// private boolean seeding_mode;
// private boolean restart_initiated;
//
// private final int _nbPieces; //how many pieces in the torrent
// private PEPieceImpl[] pePieces; //pieces that are currently in progress
// private int nbPiecesActive; // how many pieces are currently in progress
//
// private int nbPeersSnubbed;
//
// private PeerIdentityDataID _hash;
// private final byte[] _myPeerId;
// private PEPeerManagerStats _stats;
// //private final TRTrackerAnnouncer _tracker;
// // private int _maxUploads;
// private int _seeds, _peers,_remotesNoUdpNoLan;
// private long last_remote_time;
// private long _timeStarted;
// private long _timeStartedSeeding = -1;
// private long _timeFinished;
// private Average _averageReceptionSpeed;
//
// private long mainloop_loop_count;
//
// private static final int MAINLOOP_ONE_SECOND_INTERVAL = 1000 / PeerControlScheduler.SCHEDULE_PERIOD_MILLIS;
// private static final int MAINLOOP_FIVE_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 5;
// private static final int MAINLOOP_TEN_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 10;
// private static final int MAINLOOP_THIRTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 30;
// private static final int MAINLOOP_SIXTY_SECOND_INTERVAL = MAINLOOP_ONE_SECOND_INTERVAL * 60;
// private static final int MAINLOOP_TEN_MINUTE_INTERVAL = MAINLOOP_SIXTY_SECOND_INTERVAL * 10;
//
//
// private volatile ArrayList<PEPeerManagerListener> peer_manager_listeners_cow = new ArrayList<PEPeerManagerListener>(); //copy on write
//
//
// private final List<Object[]> piece_check_result_list = new ArrayList<Object[]>();
// private final AEMonitor piece_check_result_list_mon = new AEMonitor( "PEPeerControl:PCRL");
//
// private boolean superSeedMode;
// private int superSeedModeCurrentPiece;
// private int superSeedModeNumberOfAnnounces;
// private SuperSeedPiece[] superSeedPieces;
//
// private final int hidden_piece;
//
// private final AEMonitor this_mon = new AEMonitor( "PEPeerControl");
//
// private long ip_filter_last_update_time;
//
// private Map<Object,Object> user_data;
//
// private Unchoker unchoker;
//
// private List<Object[]> external_rate_limiters_cow;
//
//
// private List<PEPeer> sweepList = Collections.emptyList();
// private int nextPEXSweepIndex = 0;
//
//
// private final UploadHelper upload_helper = new UploadHelper() {
// public int getPriority() {
// return UploadHelper.PRIORITY_NORMAL; //TODO also must call UploadSlotManager.getSingleton().updateHelper( upload_helper ); on priority change
// }
//
// public ArrayList<PEPeer> getAllPeers() {
// return( peer_transports_cow );
// }
//
// public boolean isSeeding() {
// return seeding_mode;
// }
// };
//
//
//
// private PeerDatabase peer_database = PeerDatabaseFactory.createPeerDatabase();
//
// private int bad_piece_reported = -1;
//
// private int next_rescan_piece = -1;
// private long rescan_piece_time = -1;
//
// private long last_eta;
// private long last_eta_calculation;
//
// private static final int MAX_UDP_CONNECTIONS = 16;
//
// private static final int PENDING_NAT_TRAVERSAL_MAX = 32;
// private static final int MAX_UDP_TRAVERSAL_COUNT = 3;
//
// private static final String PEER_NAT_TRAVERSE_DONE_KEY = PEPeerControlImpl.class.getName() + "::nat_trav_done";
//
// private Map<String,PEPeerTransport> pending_nat_traversals =
// new LinkedHashMap<String,PEPeerTransport>(PENDING_NAT_TRAVERSAL_MAX,0.75f,true)
// {
// protected boolean
// removeEldestEntry(
// Map.Entry<String,PEPeerTransport> eldest)
// {
// return size() > PENDING_NAT_TRAVERSAL_MAX;
// }
// };
//
// private int udp_traversal_count;
//
// private static final int UDP_RECONNECT_MAX = 16;
//
// private Map<String,PEPeerTransport> udp_reconnects =
// new LinkedHashMap<String,PEPeerTransport>(UDP_RECONNECT_MAX,0.75f,true)
// {
// protected boolean
// removeEldestEntry(
// Map.Entry<String,PEPeerTransport> eldest)
// {
// return size() > UDP_RECONNECT_MAX;
// }
// };
//
// private static final int UDP_RECONNECT_MIN_MILLIS = 10*1000;
// private long last_udp_reconnect;
//
// private boolean prefer_udp;
//
// private static final int PREFER_UDP_BLOOM_SIZE = 10000;
// private volatile BloomFilter prefer_udp_bloom;
//
// private final LimitedRateGroup upload_limited_rate_group = new LimitedRateGroup() {
// public String
// getName()
// {
// return( "per_dl_up: " + getDisplayName());
// }
// public int getRateLimitBytesPerSecond() {
// return adapter.getUploadRateLimitBytesPerSecond();
// }
// };
//
// private final LimitedRateGroup download_limited_rate_group = new LimitedRateGroup() {
// public String
// getName()
// {
// return( "per_dl_down: " + getDisplayName());
// }
// public int getRateLimitBytesPerSecond() {
// return adapter.getDownloadRateLimitBytesPerSecond();
// }
// };
//
// private final int partition_id;
//
// public
// PEPeerControlImpl(
// byte[] _peer_id,
// PEPeerManagerAdapter _adapter,
// DiskManager _diskManager,
// int _partition_id )
// {
// _myPeerId = _peer_id;
// adapter = _adapter;
// disk_mgr = _diskManager;
// partition_id = _partition_id;
//
// _nbPieces =disk_mgr.getNbPieces();
// dm_pieces =disk_mgr.getPieces();
//
// pePieces = new PEPieceImpl[_nbPieces];
//
// hidden_piece = hide_a_piece?((int)(Math.abs(adapter.getRandomSeed())%_nbPieces)):-1;
//
// if ( hidden_piece >= 0 ){
//
// System.out.println( "Hidden piece for " + getDisplayName() + " = " + hidden_piece );
// }
//
// piecePicker = PiecePickerFactory.create( this );
//
// COConfigurationManager.addParameterListener("Ip Filter Enabled", this);
//
// ip_filter.addListener( this );
//
// }
//
//
// public void
// start()
// {
// //This torrent Hash
// try
// {
//
// _hash = PeerIdentityManager.createDataID( disk_mgr.getTorrent().getHash());
//
// } catch (TOTorrentException e)
// {
//
// // this should never happen
// Debug.printStackTrace( e );
//
// _hash = PeerIdentityManager.createDataID( new byte[20] );
// }
//
// // the recovered active pieces
// for (int i =0; i <_nbPieces; i++ )
// {
// final DiskManagerPiece dmPiece =dm_pieces[i];
// if (!dmPiece.isDone() &&dmPiece.getNbWritten() >0)
// {
// addPiece(new PEPieceImpl(this, dmPiece, 0), i, true );
// }
// }
//
// //The peer connections
// peer_transports_cow = new ArrayList();
//
// //BtManager is threaded, this variable represents the
// // current loop iteration. It's used by some components only called
// // at some specific times.
// mainloop_loop_count = 0;
//
// //The current tracker state
// //this could be start or update
//
// _averageReceptionSpeed = Average.getInstance(1000, 30);
//
// // the stats
// _stats =new PEPeerManagerStatsImpl(this);
//
// superSeedMode = (COConfigurationManager.getBooleanParameter("Use Super Seeding") && this.getRemaining() == 0);
//
// superSeedModeCurrentPiece = 0;
//
// if (superSeedMode)
// {
// initialiseSuperSeedMode();
// }
//
// // initial check on finished state - future checks are driven by piece check results
//
// // Moved out of mainLoop() so that it runs immediately, possibly changing
// // the state to seeding.
//
// checkFinished( true );
//
// UploadSlotManager.getSingleton().registerHelper( upload_helper );
//
// lastNeededUndonePieceChange =Long.MIN_VALUE;
// _timeStarted = SystemTime.getCurrentTime();
//
// is_running = true;
//
// // activate after marked as running as we may synchronously add connections here due to pending activations
//
// adapter.getPeerManagerRegistration().activate( this );
//
// PeerNATTraverser.getSingleton().register( this );
//
// PeerControlSchedulerFactory.getSingleton(partition_id).register(this);
// }
//
// public void stopAll()
// {
// is_running =false;
//
// UploadSlotManager.getSingleton().deregisterHelper( upload_helper );
//
// PeerControlSchedulerFactory.getSingleton(partition_id).unregister(this);
//
// PeerNATTraverser.getSingleton().unregister( this );
//
// // remove legacy controller activation
//
// adapter.getPeerManagerRegistration().deactivate();
//
// closeAndRemoveAllPeers("download stopped", false);
//
// // clear pieces
// for (int i =0; i <_nbPieces; i++ )
// {
// if (pePieces[i] !=null)
// removePiece(pePieces[i], i);
// }
//
// // 5. Remove listeners
// COConfigurationManager.removeParameterListener("Ip Filter Enabled", this);
//
// ip_filter.removeListener(this);
//
// piecePicker.destroy();
//
// final ArrayList<PEPeerManagerListener> peer_manager_listeners = peer_manager_listeners_cow;
//
// for( int i=0; i < peer_manager_listeners.size(); i++ ) {
//
// ((PEPeerManagerListener)peer_manager_listeners.get(i)).destroyed();
// }
//
// sweepList = Collections.emptyList();
//
// pending_nat_traversals.clear();
//
// udp_reconnects.clear();
//
// is_destroyed = true;
// }
//
// public int
// getPartitionID()
// {
// return( partition_id );
// }
//
// public boolean
// isDestroyed()
// {
// return( is_destroyed );
// }
//
// public DiskManager getDiskManager() { return disk_mgr; }
// public PiecePicker getPiecePicker()
// {
// return piecePicker;
// }
//
// public PEPeerManagerAdapter getAdapter(){ return( adapter ); }
//
// public String getDisplayName(){ return( adapter.getDisplayName()); }
//
// public String
// getName()
// {
// return( getDisplayName());
// }
//
// public void
// schedule()
// {
// try {
// updateTrackerAnnounceInterval();
// doConnectionChecks();
// processPieceChecks();
//
// // note that seeding_mode -> torrent totally downloaded, not just non-dnd files
// // complete, so there is no change of a new piece appearing done by a means such as
// // background periodic file rescans
//
// if ( !seeding_mode ){
//
// checkCompletedPieces(); //check to see if we've completed anything else
// }
//
// checkBadPieces();
//
// updateStats();
//
// checkInterested(); // see if need to recheck Interested on all peers
//
// piecePicker.updateAvailability();
//
// checkCompletionState(); // pick up changes in completion caused by dnd file changes
//
// checkSeeds();
//
// if(!seeding_mode) {
// // if we're not finished
//
// checkRequests();
//
// piecePicker.allocateRequests();
//
// checkRescan();
// checkSpeedAndReserved();
//
// check99PercentBug();
// }
//
//
// updatePeersInSuperSeedMode();
// doUnchokes();
//
// }catch (Throwable e) {
//
// Debug.printStackTrace( e );
// }
// mainloop_loop_count++;
// }
//
//
//
// /**
// * A private method that does analysis of the result sent by the tracker.
// * It will mainly open new connections with peers provided
// * and set the timeToWait variable according to the tracker response.
// * @param tracker_response
// */
//
// private void
// analyseTrackerResponse(
// TRTrackerAnnouncerResponse tracker_response )
// {
// // tracker_response.print();
// final TRTrackerAnnouncerResponsePeer[] peers = tracker_response.getPeers();
//
// if ( peers != null ){
// addPeersFromTracker( tracker_response.getPeers());
// }
//
// final Map extensions = tracker_response.getExtensions();
//
// if (extensions != null ){
// addExtendedPeersFromTracker( extensions );
// }
// }
//
// public void
// processTrackerResponse(
// TRTrackerAnnouncerResponse response )
// {
// // only process new peers if we're still running
// if ( is_running ){
// analyseTrackerResponse( response );
// }
// }
//
// private void
// addExtendedPeersFromTracker(
// Map extensions )
// {
// final Map protocols = (Map)extensions.get("protocols");
//
// if ( protocols != null ){
//
// System.out.println( "PEPeerControl: tracker response contained protocol extensions");
//
// final Iterator protocol_it = protocols.keySet().iterator();
//
// while( protocol_it.hasNext()){
//
// final String protocol_name = (String)protocol_it.next();
//
// final Map protocol = (Map)protocols.get(protocol_name);
//
// final List transports = PEPeerTransportFactory.createExtendedTransports( this, protocol_name, protocol );
//
// for (int i=0;i<transports.size();i++){
//
// final PEPeer transport = (PEPeer)transports.get(i);
//
// addPeer( transport );
// }
// }
// }
// }
//
// public List<PEPeer>
// getPeers()
// {
// return( peer_transports_cow );
// }
//
// public List<PEPeer>
// getPeers(
// String address )
// {
// List<PEPeer> result = new ArrayList<PEPeer>();
//
// Iterator<PEPeer> it = peer_transports_cow.iterator();
//
// while( it.hasNext()){
//
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// if ( peer.getIp().equals( address )){
//
// result.add( peer );
// }
// }
//
// return( result );
// }
//
// public PeerDescriptor[]
// getPendingPeers()
// {
// return((PeerDescriptor[])peer_database.getDiscoveredPeers());
// }
//
// public PeerDescriptor[]
// getPendingPeers(
// String address )
// {
// return((PeerDescriptor[])peer_database.getDiscoveredPeers( address ));
// }
//
// public void
// addPeer(
// PEPeer _transport )
// {
// if ( !( _transport instanceof PEPeerTransport )){
//
// throw( new RuntimeException("invalid class"));
// }
//
// final PEPeerTransport transport = (PEPeerTransport)_transport;
//
// if (!ip_filter.isInRange(transport.getIp(), getDisplayName(), getTorrentHash())) {
//
// final ArrayList peer_transports = peer_transports_cow;
//
// if ( !peer_transports.contains(transport)){
//
// addToPeerTransports( transport );
//
// transport.start();
//
// }else{
// Debug.out( "addPeer():: peer_transports.contains(transport): SHOULD NEVER HAPPEN !" );
// transport.closeConnection( "already connected" );
// }
// }else{
//
// transport.closeConnection( "IP address blocked by filters" );
// }
// }
//
// protected byte[]
// getTorrentHash()
// {
// try{
// return( disk_mgr.getTorrent().getHash());
//
// }catch( Throwable e ){
//
// return( null );
// }
// }
// public void
// removePeer(
// PEPeer _transport )
// {
// removePeer( _transport, "remove peer" );
// }
//
// public void
// removePeer(
// PEPeer _transport,
// String reason )
// {
// if ( !( _transport instanceof PEPeerTransport )){
//
// throw( new RuntimeException("invalid class"));
// }
//
// PEPeerTransport transport = (PEPeerTransport)_transport;
//
// closeAndRemovePeer( transport, reason, true );
// }
//
// private void closeAndRemovePeer( PEPeerTransport peer, String reason, boolean log_if_not_found )
// {
// boolean removed =false;
//
// // copy-on-write semantics
// try{
// peer_transports_mon.enter();
//
// if ( peer_transports_cow.contains( peer )){
//
// final ArrayList new_peer_transports = new ArrayList( peer_transports_cow );
//
// new_peer_transports.remove(peer);
// peer_transports_cow =new_peer_transports;
// removed =true;
// }
// }
// finally{
// peer_transports_mon.exit();
// }
//
// if( removed ) {
// peer.closeConnection( reason );
// peerRemoved(peer); //notify listeners
// }
// else {
// if ( log_if_not_found ){
// // we know this happens due to timing issues... Debug.out( "closeAndRemovePeer(): peer not removed" );
// }
// }
// }
//
// private void closeAndRemoveAllPeers( String reason, boolean reconnect ) {
// ArrayList peer_transports;
//
// try{
// peer_transports_mon.enter();
//
// peer_transports = peer_transports_cow;
//
// peer_transports_cow = new ArrayList( 0 );
// }
// finally{
// peer_transports_mon.exit();
// }
//
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
//
// try{
//
// peer.closeConnection( reason );
//
// }catch( Throwable e ){
//
// // if something goes wrong with the close process (there's a bug in there somewhere whereby
// // we occasionally get NPEs then we want to make sure we carry on and close the rest
//
// Debug.printStackTrace(e);
// }
//
// try{
// peerRemoved( peer ); //notify listeners
//
// }catch( Throwable e ){
//
// Debug.printStackTrace(e);
// }
// }
//
// if( reconnect ) {
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
//
// PEPeerTransport reconnected_peer = peer.reconnect(false, false);
// }
// }
// }
//
//
//
//
// public void
// addPeer(
// String ip_address,
// int tcp_port,
// int udp_port,
// boolean use_crypto,
// Map user_data )
// {
// final byte type = use_crypto ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN;
// final PeerItem peer_item = PeerItemFactory.createPeerItem( ip_address, tcp_port, PeerItem.convertSourceID( PEPeerSource.PS_PLUGIN ), type, udp_port, PeerItemFactory.CRYPTO_LEVEL_1, 0 );
//
// byte crypto_level = PeerItemFactory.CRYPTO_LEVEL_1;
//
// if( !isAlreadyConnected( peer_item ) ) {
//
// String fail_reason;
//
// boolean tcp_ok = TCPNetworkManager.TCP_OUTGOING_ENABLED && tcp_port > 0;
// boolean udp_ok = UDPNetworkManager.UDP_OUTGOING_ENABLED && udp_port > 0;
//
// if ( tcp_ok && !( ( prefer_udp || prefer_udp_default ) && udp_ok )){
//
// fail_reason = makeNewOutgoingConnection( PEPeerSource.PS_PLUGIN, ip_address, tcp_port, udp_port, true, use_crypto, crypto_level, user_data ); //directly inject the the imported peer
//
// }else if ( udp_ok ){
//
// fail_reason = makeNewOutgoingConnection( PEPeerSource.PS_PLUGIN, ip_address, tcp_port, udp_port, false, use_crypto, crypto_level, user_data ); //directly inject the the imported peer
//
// }else{
//
// fail_reason = "No usable protocol";
// }
//
// if( fail_reason != null ) Debug.out( "Injected peer " + ip_address + ":" + tcp_port + " was not added - " + fail_reason );
// }
// }
//
//
//
// private void
// addPeersFromTracker(
// TRTrackerAnnouncerResponsePeer[] peers )
// {
//
// for (int i = 0; i < peers.length; i++){
// final TRTrackerAnnouncerResponsePeer peer = peers[i];
//
// final ArrayList peer_transports = peer_transports_cow;
//
// boolean already_connected = false;
//
// for( int x=0; x < peer_transports.size(); x++ ) {
// final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( x );
//
// // allow loopback connects for co-located proxy-based connections and testing
//
// if( peer.getAddress().equals( transport.getIp() )){
//
// final boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) ||
//
// transport.getIp().equals( "127.0.0.1" );
//
// if( !same_allowed || peer.getPort() == transport.getPort() ) {
// already_connected = true;
// break;
// }
// }
// }
//
// if( already_connected ) continue;
//
// if( peer_database != null ){
//
// byte type = peer.getProtocol() == DownloadAnnounceResultPeer.PROTOCOL_CRYPT ? PeerItemFactory.HANDSHAKE_TYPE_CRYPTO : PeerItemFactory.HANDSHAKE_TYPE_PLAIN;
//
// byte crypto_level = peer.getAZVersion() < TRTrackerAnnouncer.AZ_TRACKER_VERSION_3?PeerItemFactory.CRYPTO_LEVEL_1:PeerItemFactory.CRYPTO_LEVEL_2;
//
// PeerItem item = PeerItemFactory.createPeerItem(
// peer.getAddress(),
// peer.getPort(),
// PeerItem.convertSourceID( peer.getSource() ),
// type,
// peer.getUDPPort(),
// crypto_level,
// peer.getUploadSpeed());
//
// peerDiscovered( null, item );
//
// peer_database.addDiscoveredPeer( item );
// }
//
// int http_port = peer.getHTTPPort();
//
// if ( http_port != 0 ){
//
// adapter.addHTTPSeed( peer.getAddress(), http_port );
// }
// }
// }
//
//
// /**
// * Request a new outgoing peer connection.
// * @param address ip of remote peer
// * @param port remote peer listen port
// * @return null if the connection was added to the transport list, reason if rejected
// */
//
// private String
// makeNewOutgoingConnection(
// String peer_source,
// String address,
// int tcp_port,
// int udp_port,
// boolean use_tcp,
// boolean require_crypto,
// byte crypto_level,
// Map user_data )
// {
// //make sure this connection isn't filtered
//
// if( ip_filter.isInRange( address, getDisplayName(), getTorrentHash())) {
// return "IPFilter block";
// }
//
// //make sure we need a new connection
// final int needed = getMaxNewConnectionsAllowed();
//
// boolean is_priority_connection = false;
//
// if ( user_data != null ){
//
// Boolean pc = (Boolean)user_data.get( Peer.PR_PRIORITY_CONNECTION );
//
// if ( pc != null && pc.booleanValue()){
//
// is_priority_connection = true;
// }
// }
//
// if( needed == 0 ){
//
// if ( peer_source != PEPeerSource.PS_PLUGIN ||
// !doOptimisticDisconnect(
// AddressUtils.isLANLocalAddress( address ) != AddressUtils.LAN_LOCAL_NO,
// is_priority_connection )){
//
// return "Too many connections";
// }
// }
//
// //make sure not already connected to the same IP address; allow loopback connects for co-located proxy-based connections and testing
// final boolean same_allowed = COConfigurationManager.getBooleanParameter( "Allow Same IP Peers" ) || address.equals( "127.0.0.1" );
// if( !same_allowed && PeerIdentityManager.containsIPAddress( _hash, address ) ){
// return "Already connected to IP";
// }
//
// if( PeerUtils.ignorePeerPort( tcp_port ) ) {
// if (Logger.isEnabled())
// Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID,
// "Skipping connect with " + address + ":" + tcp_port
// + " as peer port is in ignore list."));
// return "TCP port in ignore list";
// }
//
// //start the connection
//
// PEPeerTransport real = PEPeerTransportFactory.createTransport( this, peer_source, address, tcp_port, udp_port, use_tcp, require_crypto, crypto_level, user_data );
//
// addToPeerTransports( real );
//
// return null;
// }
//
//
// /**
// * A private method that checks if PEPieces being downloaded are finished
// * If all blocks from a PEPiece are written to disk, this method will
// * queue the piece for hash check.
// * Elsewhere, if it passes sha-1 check, it will be marked as downloaded,
// * otherwise, it will unmark it as fully downloaded, so blocks can be retreived again.
// */
// private void checkCompletedPieces() {
// if ((mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) !=0)
// return;
//
// //for every piece
// for (int i = 0; i <_nbPieces; i++) {
// final DiskManagerPiece dmPiece =dm_pieces[i];
// //if piece is completly written, not already checking, and not Done
// if (dmPiece.isNeedsCheck())
// {
// //check the piece from the disk
// dmPiece.setChecking();
//
// DiskManagerCheckRequest req =
// disk_mgr.createCheckRequest(
// i, new Integer(CHECK_REASON_DOWNLOADED));
//
// req.setAdHoc( false );
//
// disk_mgr.enqueueCheckRequest( req, this );
// }
// }
// }
//
// /** Checks given piece to see if it's active but empty, and if so deactivates it.
// * @param pieceNumber to check
// * @return true if the piece was removed and is no longer active (pePiece ==null)
// */
// private boolean
// checkEmptyPiece(
// final int pieceNumber )
// {
// if ( piecePicker.isInEndGameMode()){
//
// return false; // be sure to not remove pieces in EGM
// }
//
// final PEPiece pePiece =pePieces[pieceNumber];
// final DiskManagerPiece dmPiece =dm_pieces[pieceNumber];
//
// if ( pePiece == null || pePiece.isRequested())
// return false;
//
// if (dmPiece.getNbWritten() >0 ||pePiece.getNbUnrequested() < pePiece.getNbBlocks() ||pePiece.getReservedBy() !=null)
// return false;
//
// // reset in case dmpiece is in some skanky state
//
// pePiece.reset();
//
// removePiece(pePiece, pieceNumber);
// return true;
// }
//
// /**
// * Check if a piece's Speed is too fast for it to be getting new data
// * and if a reserved pieced failed to get data within 120 seconds
// */
// private void checkSpeedAndReserved()
// {
// // only check every 5 seconds
// if(mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL != 0)
// return;
//
// final int nbPieces =_nbPieces;
// final PEPieceImpl[] pieces =pePieces;
// //for every piece
// for (int i =0; i <nbPieces; i++)
// {
// // placed before null-check in case it really removes a piece
// checkEmptyPiece(i);
//
//
// final PEPieceImpl pePiece =pieces[i];
// // these checks are only against pieces being downloaded
// // yet needing requests still/again
// if (pePiece !=null)
// {
// final long timeSinceActivity =pePiece.getTimeSinceLastActivity()/1000;
//
// int pieceSpeed =pePiece.getSpeed();
// // block write speed slower than piece speed
// if (pieceSpeed > 0 && timeSinceActivity*pieceSpeed*0.25 > DiskManager.BLOCK_SIZE/1024)
// {
// if(pePiece.getNbUnrequested() > 2)
// pePiece.setSpeed(pieceSpeed-1);
// else
// pePiece.setSpeed(0);
// }
//
//
// if(timeSinceActivity > 120)
// {
// pePiece.setSpeed(0);
// // has reserved piece gone stagnant?
// final String reservingPeer =pePiece.getReservedBy();
// if(reservingPeer !=null)
// {
// final PEPeerTransport pt = getTransportFromAddress(reservingPeer);
// // Peer is too slow; Ban them and unallocate the piece
// // but, banning is no good for peer types that get pieces reserved
// // to them for other reasons, such as special seed peers
// if (needsMD5CheckOnCompletion(i))
// badPeerDetected(reservingPeer, i);
// else if (pt != null)
// closeAndRemovePeer(pt, "Reserved piece data timeout; 120 seconds", true);
//
// pePiece.setReservedBy(null);
// }
//
// if (!piecePicker.isInEndGameMode()){
// pePiece.checkRequests();
// }
//
// checkEmptyPiece(i);
// }
//
// }
// }
// }
//
// private void
// check99PercentBug()
// {
// // there's a bug whereby pieces are left downloaded but never written. might have been fixed by
// // changes to the "write result" logic, however as a stop gap I'm adding code to scan for such
// // stuck pieces and reset them
//
// if ( mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0 ) {
//
// long now = SystemTime.getCurrentTime();
//
// for ( int i=0;i<pePieces.length;i++){
//
// PEPiece pe_piece = pePieces[ i ];
//
// if ( pe_piece != null ){
//
// DiskManagerPiece dm_piece = dm_pieces[i];
//
// if ( !dm_piece.isDone()){
//
// if ( pe_piece.isDownloaded()){
//
// if ( now - pe_piece.getLastDownloadTime(now) > stalled_piece_timeout ){
//
// // people with *very* slow disk writes can trigger this (I've been talking to a user
// // with a SAN that has .5 second write latencies when checking a file at the same time
// // this means that when dowloading > 32K/sec things start backing up). Eventually the
// // write controller will start blocking the network thread to prevent unlimited
// // queueing but until that time we need to handle this situation slightly better)
//
// // if there are any outstanding requests for this piece then leave it alone
//
// if ( !( disk_mgr.hasOutstandingWriteRequestForPiece( i ) ||
// disk_mgr.hasOutstandingReadRequestForPiece( i ) ||
// disk_mgr.hasOutstandingCheckRequestForPiece( i ) )){
//
// Debug.out( "Fully downloaded piece stalled pending write, resetting p_piece " + i );
//
// pe_piece.reset();
// }
// }
// }
// }
// }
//
// }
// }
// }
//
// private void checkInterested()
// {
// if ( (mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) != 0 ){
// return;
// }
//
// if (lastNeededUndonePieceChange >=piecePicker.getNeededUndonePieceChange())
// return;
//
// lastNeededUndonePieceChange =piecePicker.getNeededUndonePieceChange();
//
// final ArrayList peer_transports = peer_transports_cow;
// int cntPeersSnubbed =0; // recount # snubbed peers while we're at it
// for (int i =0; i <peer_transports.size(); i++)
// {
// final PEPeerTransport peer =(PEPeerTransport)peer_transports.get(i);
// peer.checkInterested();
// if (peer.isSnubbed())
// cntPeersSnubbed++;
// }
// setNbPeersSnubbed(cntPeersSnubbed);
// }
//
//
// /**
// * Private method to process the results given by DiskManager's
// * piece checking thread via asyncPieceChecked(..)
// */
// private void
// processPieceChecks()
// {
// if ( piece_check_result_list.size() > 0 ){
//
// final List pieces;
//
// // process complete piece results
//
// try{
// piece_check_result_list_mon.enter();
//
// pieces = new ArrayList( piece_check_result_list );
//
// piece_check_result_list.clear();
//
// }finally{
//
// piece_check_result_list_mon.exit();
// }
//
// final Iterator it = pieces.iterator();
//
// while (it.hasNext()) {
//
// final Object[] data = (Object[])it.next();
//
// processPieceCheckResult((DiskManagerCheckRequest)data[0],((Integer)data[1]).intValue());
//
// }
// }
// }
//
// private void
// checkBadPieces()
// {
// if ( mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0 ){
//
// if ( bad_piece_reported != -1 ){
//
// DiskManagerCheckRequest req =
// disk_mgr.createCheckRequest(
// bad_piece_reported,
// new Integer( CHECK_REASON_BAD_PIECE_CHECK ));
//
// req.setLowPriority( true );
//
// if ( Logger.isEnabled()){
//
// Logger.log(
// new LogEvent(
// disk_mgr.getTorrent(), LOGID,
// "Rescanning reported-bad piece " + bad_piece_reported ));
//
// }
//
// bad_piece_reported = -1;
//
// try{
// disk_mgr.enqueueCheckRequest( req, this );
//
// }catch( Throwable e ){
//
//
// Debug.printStackTrace(e);
// }
// }
// }
// }
//
// private void
// checkRescan()
// {
// if ( rescan_piece_time == 0 ){
//
// // pending a piece completion
//
// return;
// }
//
// if ( next_rescan_piece == -1 ){
//
// if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL == 0 ){
//
// if ( adapter.isPeriodicRescanEnabled()){
//
// next_rescan_piece = 0;
// }
// }
// }else{
//
// if ( mainloop_loop_count % MAINLOOP_TEN_MINUTE_INTERVAL == 0 ){
//
// if ( !adapter.isPeriodicRescanEnabled()){
//
// next_rescan_piece = -1;
// }
// }
// }
//
// if ( next_rescan_piece == -1 ){
//
// return;
// }
//
// // delay as required
//
// final long now = SystemTime.getCurrentTime();
//
// if ( rescan_piece_time > now ){
//
// rescan_piece_time = now;
// }
//
// // 250K/sec limit
//
// final long piece_size = disk_mgr.getPieceLength();
//
// final long millis_per_piece = piece_size / 250;
//
// if ( now - rescan_piece_time < millis_per_piece ){
//
// return;
// }
//
// while( next_rescan_piece != -1 ){
//
// int this_piece = next_rescan_piece;
//
// next_rescan_piece++;
//
// if ( next_rescan_piece == _nbPieces ){
//
// next_rescan_piece = -1;
// }
//
// // this functionality is to pick up pieces that have been downloaded OUTSIDE of
// // Azureus - e.g. when two torrents are sharing a single file. Hence the check on
// // the piece NOT being done
//
// if ( pePieces[this_piece] == null && !dm_pieces[this_piece].isDone() && dm_pieces[this_piece].isNeeded()){
//
// DiskManagerCheckRequest req =
// disk_mgr.createCheckRequest(
// this_piece,
// new Integer( CHECK_REASON_SCAN ));
//
// req.setLowPriority( true );
//
// if ( Logger.isEnabled()){
//
// Logger.log(
// new LogEvent(
// disk_mgr.getTorrent(), LOGID,
// "Rescanning piece " + this_piece ));
//
// }
//
// rescan_piece_time = 0; // mark as check piece in process
//
// try{
// disk_mgr.enqueueCheckRequest( req, this );
//
// }catch( Throwable e ){
//
// rescan_piece_time = now;
//
// Debug.printStackTrace(e);
// }
//
// break;
// }
// }
// }
//
// public void
// badPieceReported(
// PEPeerTransport originator,
// int piece_number )
// {
// Debug.outNoStack( getDisplayName() + ": bad piece #" + piece_number + " reported by " + originator.getIp());
//
// if ( piece_number < 0 || piece_number >= _nbPieces ){
//
// return;
// }
//
// bad_piece_reported = piece_number;
// }
//
// /**
// * This method checks if the downloading process is finished.
// *
// */
// private void
// checkFinished(
// boolean start_of_day )
// {
// final boolean all_pieces_done =disk_mgr.getRemainingExcludingDND() ==0;
//
// if (all_pieces_done)
// {
// seeding_mode = true;
//
// prefer_udp_bloom = null;
//
// piecePicker.clearEndGameChunks();
//
// if (!start_of_day)
// adapter.setStateFinishing();
//
// _timeFinished = SystemTime.getCurrentTime();
// final ArrayList peer_transports = peer_transports_cow;
//
// //remove previous snubbing
// for (int i =0; i <peer_transports.size(); i++ )
// {
// final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
// pc.setSnubbed(false);
// }
// setNbPeersSnubbed(0);
//
// final boolean checkPieces =COConfigurationManager.getBooleanParameter( "Check Pieces on Completion" );
//
// //re-check all pieces to make sure they are not corrupt, but only if we weren't already complete
// if (checkPieces &&!start_of_day)
// {
// final DiskManagerCheckRequest req =disk_mgr.createCheckRequest(-1, new Integer(CHECK_REASON_COMPLETE));
// disk_mgr.enqueueCompleteRecheckRequest(req, this);
// }
//
// _timeStartedSeeding = SystemTime.getCurrentTime();
//
// try{
// disk_mgr.saveResumeData(false);
//
// }catch( Throwable e ){
// Debug.out( "Failed to save resume data", e );
// }
// adapter.setStateSeeding( start_of_day );
// disk_mgr.downloadEnded();
// } else
// {
// seeding_mode = false;
// }
// }
//
// protected void
// checkCompletionState()
// {
// if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL != 0 ){
//
// return;
// }
//
// boolean dm_done = disk_mgr.getRemainingExcludingDND() == 0;
//
// if ( seeding_mode ){
//
// if ( !dm_done ){
//
// seeding_mode = false;
//
// _timeStartedSeeding = -1;
// _timeFinished = 0;
//
// Logger.log(
// new LogEvent( disk_mgr.getTorrent(), LOGID,
// "Turning off seeding mode for PEPeerManager"));
// }
// }else{
//
// if ( dm_done ){
//
// checkFinished( false );
//
// if ( seeding_mode ){
//
// Logger.log(
// new LogEvent( disk_mgr.getTorrent(), LOGID,
// "Turning on seeding mode for PEPeerManager"));
// }
// }
// }
// }
//
// /**
// * This method will locate expired requests on peers, will cancel them,
// * and mark the peer as snubbed if we haven't received usefull data from
// * them within the last 60 seconds
// */
// private void checkRequests()
// {
// // to be honest I don't see why this can't be 5 seconds, but I'm trying 1 second
// // now as the existing 0.1 second is crazy given we're checking for events that occur
// // at 60+ second intervals
//
// if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL != 0 ){
//
// return;
// }
//
// final long now =SystemTime.getCurrentTime();
//
// //for every connection
// final ArrayList peer_transports = peer_transports_cow;
// for (int i =peer_transports.size() -1; i >=0 ; i--)
// {
// final PEPeerTransport pc =(PEPeerTransport)peer_transports.get(i);
// if (pc.getPeerState() ==PEPeer.TRANSFERING)
// {
// final List expired = pc.getExpiredRequests();
// if (expired !=null &&expired.size() >0)
// { // now we know there's a request that's > 60 seconds old
// final boolean isSeed =pc.isSeed();
// // snub peers that haven't sent any good data for a minute
// final long timeSinceGoodData =pc.getTimeSinceGoodDataReceived();
// if (timeSinceGoodData <0 ||timeSinceGoodData >60 *1000)
// pc.setSnubbed(true);
//
// //Only cancel first request if more than 2 mins have passed
// DiskManagerReadRequest request =(DiskManagerReadRequest) expired.get(0);
//
// final long timeSinceData =pc.getTimeSinceLastDataMessageReceived();
// final boolean noData =(timeSinceData <0) ||timeSinceData >(1000 *(isSeed ?120 :60));
// final long timeSinceOldestRequest = now - request.getTimeCreated(now);
//
//
// //for every expired request
// for (int j = (timeSinceOldestRequest >120 *1000 && noData) ? 0 : 1; j < expired.size(); j++)
// {
// //get the request object
// request =(DiskManagerReadRequest) expired.get(j);
// //Only cancel first request if more than 2 mins have passed
// pc.sendCancel(request); //cancel the request object
// //get the piece number
// final int pieceNumber = request.getPieceNumber();
// PEPiece pe_piece = pePieces[pieceNumber];
// //unmark the request on the block
// if ( pe_piece != null )
// pe_piece.clearRequested(request.getOffset() /DiskManager.BLOCK_SIZE);
// // remove piece if empty so peers can choose something else, except in end game
// if (!piecePicker.isInEndGameMode())
// checkEmptyPiece(pieceNumber);
// }
// }
// }
// }
// }
//
// private void
// updateTrackerAnnounceInterval()
// {
// if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL != 0 ){
// return;
// }
//
// final int WANT_LIMIT = 100;
//
// int num_wanted = getMaxNewConnectionsAllowed();
//
// final boolean has_remote = adapter.isNATHealthy();
// if( has_remote ) {
// //is not firewalled, so can accept incoming connections,
// //which means no need to continually keep asking the tracker for peers
// num_wanted = (int)(num_wanted / 1.5);
// }
//
// if ( num_wanted < 0 || num_wanted > WANT_LIMIT ) {
// num_wanted = WANT_LIMIT;
// }
//
// int current_connection_count = PeerIdentityManager.getIdentityCount( _hash );
//
// final TRTrackerScraperResponse tsr = adapter.getTrackerScrapeResponse();
//
// if( tsr != null && tsr.isValid() ) { //we've got valid scrape info
// final int num_seeds = tsr.getSeeds();
// final int num_peers = tsr.getPeers();
//
// final int swarm_size;
//
// if( seeding_mode ) {
// //Only use peer count when seeding, as other seeds are unconnectable.
// //Since trackers return peers randomly (some of which will be seeds),
// //backoff by the seed2peer ratio since we're given only that many peers
// //on average each announce.
// final float ratio = (float)num_peers / (num_seeds + num_peers);
// swarm_size = (int)(num_peers * ratio);
// }
// else {
// swarm_size = num_peers + num_seeds;
// }
//
// if( swarm_size < num_wanted ) { //lower limit to swarm size if necessary
// num_wanted = swarm_size;
// }
// }
//
// if( num_wanted < 1 ) { //we dont need any more connections
// adapter.setTrackerRefreshDelayOverrides( 100 ); //use normal announce interval
// return;
// }
//
// if( current_connection_count == 0 ) current_connection_count = 1; //fudge it :)
//
// final int current_percent = (current_connection_count * 100) / (current_connection_count + num_wanted);
//
// adapter.setTrackerRefreshDelayOverrides( current_percent ); //set dynamic interval override
// }
//
// public boolean
// hasDownloadablePiece()
// {
// return( piecePicker.hasDownloadablePiece());
// }
//
// public int[] getAvailability()
// {
// return piecePicker.getAvailability();
// }
//
// //this only gets called when the My Torrents view is displayed
// public float getMinAvailability()
// {
// return piecePicker.getMinAvailability();
// }
//
// public float getAvgAvail()
// {
// return piecePicker.getAvgAvail();
// }
//
// public long getAvailWentBadTime()
// {
// return( piecePicker.getAvailWentBadTime());
// }
//
// public void addPeerTransport( PEPeerTransport transport ) {
// if (!ip_filter.isInRange(transport.getIp(), getDisplayName(), getTorrentHash())) {
// final ArrayList peer_transports = peer_transports_cow;
//
// if (!peer_transports.contains( transport )) {
// addToPeerTransports(transport);
// }
// else{
// Debug.out( "addPeerTransport():: peer_transports.contains(transport): SHOULD NEVER HAPPEN !" );
// transport.closeConnection( "already connected" );
// }
// }
// else {
// transport.closeConnection( "IP address blocked by filters" );
// }
// }
//
//
// /**
// * Do all peer choke/unchoke processing.
// */
// private void doUnchokes() {
//
// // logic below is either 1 second or 10 secondly, bail out early id neither
//
// if( !UploadSlotManager.AUTO_SLOT_ENABLE ) { //manual per-torrent unchoke slot mode
//
// if( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL != 0 ) {
// return;
// }
//
// final int max_to_unchoke = adapter.getMaxUploads(); //how many simultaneous uploads we should consider
// final ArrayList peer_transports = peer_transports_cow;
//
// //determine proper unchoker
// if( seeding_mode ) {
// if( unchoker == null || !(unchoker.isSeedingUnchoker()) ) {
// unchoker = UnchokerFactory.getSingleton().getUnchoker( true );
// }
// }
// else {
// if( unchoker == null || unchoker.isSeedingUnchoker()) {
// unchoker = UnchokerFactory.getSingleton().getUnchoker( false );
// }
// }
//
// //do main choke/unchoke update every 10 secs
//
// if ( mainloop_loop_count % MAINLOOP_TEN_SECOND_INTERVAL == 0 ){
//
// final boolean refresh = mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0;
//
// unchoker.calculateUnchokes( max_to_unchoke, peer_transports, refresh, adapter.hasPriorityConnection());
//
// ArrayList chokes = unchoker.getChokes();
// ArrayList unchokes = unchoker.getUnchokes();
//
// addFastUnchokes( unchokes );
//
// UnchokerUtil.performChokes( chokes, unchokes );
//
// }else if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL == 0 ) { //do quick unchoke check every 1 sec
//
// ArrayList unchokes = unchoker.getImmediateUnchokes( max_to_unchoke, peer_transports );
//
// addFastUnchokes( unchokes );
//
// UnchokerUtil.performChokes( null, unchokes );
// }
// }
// }
//
// private void
// addFastUnchokes(
// ArrayList peers_to_unchoke )
// {
// for( Iterator it=peer_transports_cow.iterator();it.hasNext();) {
//
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// if ( peer.getConnectionState() != PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ||
// !UnchokerUtil.isUnchokable( peer, true ) ||
// peers_to_unchoke.contains( peer )){
//
// continue;
// }
//
// if( peer.isLANLocal()){
//
// peers_to_unchoke.add( peer );
//
// }else if ( fast_unchoke_new_peers &&
// peer.getData( "fast_unchoke_done" ) == null ){
//
// peer.setData( "fast_unchoke_done", "" );
//
// peers_to_unchoke.add( peer );
// }
// }
// }
//
//// send the have requests out
// private void sendHave(int pieceNumber) {
// //fo
// final ArrayList peer_transports = peer_transports_cow;
//
// for (int i = 0; i < peer_transports.size(); i++) {
// //get a peer connection
// final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
// //send the have message
// pc.sendHave(pieceNumber);
// }
//
// }
//
// // Method that checks if we are connected to another seed, and if so, disconnect from him.
// private void checkSeeds() {
// //proceed on mainloop 1 second intervals if we're a seed and we want to force disconnects
// if ((mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL) != 0)
// return;
//
// if (!disconnect_seeds_when_seeding ){
// return;
// }
//
// ArrayList to_close = null;
//
// final ArrayList peer_transports = peer_transports_cow;
// for (int i = 0; i < peer_transports.size(); i++) {
// final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
//
// if (pc != null && pc.getPeerState() == PEPeer.TRANSFERING && ((isSeeding() && pc.isSeed()) || pc.isRelativeSeed())) {
// if( to_close == null ) to_close = new ArrayList();
// to_close.add( pc );
// }
// }
//
// if( to_close != null ) {
// for( int i=0; i < to_close.size(); i++ ) {
// closeAndRemovePeer( (PEPeerTransport)to_close.get(i), "disconnect other seed when seeding", false );
// }
// }
// }
//
//
//
//
// private void updateStats() {
//
// if ( (mainloop_loop_count %MAINLOOP_ONE_SECOND_INTERVAL) != 0 ){
// return;
// }
//
// //calculate seeds vs peers
// final ArrayList peer_transports = peer_transports_cow;
//
// int new_seeds = 0;
// int new_peers = 0;
// int newTcpRemotes = 0;
//
// for (Iterator it=peer_transports.iterator();it.hasNext();){
// final PEPeerTransport pc = (PEPeerTransport) it.next();
// if (pc.getPeerState() == PEPeer.TRANSFERING) {
// if (pc.isSeed())
// new_seeds++;
// else
// new_peers++;
//
// if(pc.isIncoming() && pc.isTCP() && !pc.isLANLocal()) {
// newTcpRemotes++;
// }
// }
// }
//
// _seeds = new_seeds;
// _peers = new_peers;
// _remotesNoUdpNoLan = newTcpRemotes;
// }
// /**
// * The way to unmark a request as being downloaded, or also
// * called by Peer connections objects when connection is closed or choked
// * @param request a DiskManagerReadRequest holding details of what was canceled
// */
// public void requestCanceled(DiskManagerReadRequest request)
// {
// final int pieceNumber =request.getPieceNumber(); //get the piece number
// PEPiece pe_piece = pePieces[pieceNumber];
// if (pe_piece != null )
// pe_piece.clearRequested(request.getOffset() /DiskManager.BLOCK_SIZE);
// }
//
//
// public PEPeerControl
// getControl()
// {
// return( this );
// }
//
// public byte[][]
// getSecrets(
// int crypto_level )
// {
// return( adapter.getSecrets( crypto_level ));
// }
//
//// get the hash value
// public byte[] getHash() {
// return _hash.getDataID();
// }
//
// public PeerIdentityDataID
// getPeerIdentityDataID()
// {
// return( _hash );
// }
//
//// get the peer id value
// public byte[] getPeerId() {
// return _myPeerId;
// }
//
//// get the remaining percentage
// public long getRemaining() {
// return disk_mgr.getRemaining();
// }
//
//
// public void discarded(PEPeer peer, int length) {
// if (length > 0){
// _stats.discarded(peer, length);
//
// // discards are more likely during end-game-mode
//
// if ( ban_peer_discard_ratio > 0 && !( piecePicker.isInEndGameMode() || piecePicker.hasEndGameModeBeenAbandoned())){
//
// long received = peer.getStats().getTotalDataBytesReceived();
// long discarded = peer.getStats().getTotalBytesDiscarded();
//
// long non_discarded = received - discarded;
//
// if ( non_discarded < 0 ){
//
// non_discarded = 0;
// }
//
// if ( discarded >= ban_peer_discard_min_kb * 1024 ){
//
// if ( non_discarded == 0 ||
// ((float)discarded) / non_discarded >= ban_peer_discard_ratio ){
//
// badPeerDetected( peer.getIp(), -1 );
// }
// }
// }
// }
// }
//
// public void dataBytesReceived(PEPeer peer, int length) {
// if (length > 0) {
// _stats.dataBytesReceived(peer,length);
//
// _averageReceptionSpeed.addValue(length);
// }
// }
//
//
// public void protocolBytesReceived(PEPeer peer, int length ) {
// if (length > 0) {
// _stats.protocolBytesReceived(peer,length);
// }
// }
//
// public void dataBytesSent(PEPeer peer, int length) {
// if (length > 0) {
// _stats.dataBytesSent(peer, length );
// }
// }
//
//
// public void protocolBytesSent( PEPeer peer, int length ) {
// if (length > 0) {
// _stats.protocolBytesSent(peer,length);
// }
// }
//
// /** DiskManagerWriteRequestListener message
// * @see org.gudy.azureus2.core3.disk.DiskManagerWriteRequestListener
// */
// public void writeCompleted(DiskManagerWriteRequest request)
// {
// final int pieceNumber =request.getPieceNumber();
//
// DiskManagerPiece dm_piece = dm_pieces[pieceNumber];
//
// if (!dm_piece.isDone()){
//
// final PEPiece pePiece =pePieces[pieceNumber];
//
// if (pePiece !=null){
//
// pePiece.setWritten((PEPeer)request.getUserData(), request.getOffset() /DiskManager.BLOCK_SIZE );
//
// }else{
//
// // this is a way of fixing a 99.9% bug where a dmpiece is left in a
// // fully downloaded state with the underlying pe_piece null. Possible explanation is
// // that a slow peer sends an entire piece at around the time a pe_piece gets reset
// // due to inactivity.
//
// // we also get here when recovering data that has come in late after the piece has
// // been abandoned
//
// dm_piece.setWritten( request.getOffset() /DiskManager.BLOCK_SIZE );
// }
// }
// }
//
// public void
// writeFailed(
// DiskManagerWriteRequest request,
// Throwable cause )
// {
// // if the write has failed then the download will have been stopped so there is no need to try
// // and reset the piece
// }
//
//
// /**
// *
// * @param data_offset MUST be block aligned within the TORRENT
// * @param data
// * @return buffers not yet written
// * @throws Exception
// */
//
// public DirectByteBuffer[]
// write(
// long data_offset,
// DirectByteBuffer[] data )
//
// throws Exception
// {
// if ( data_offset % DiskManager.BLOCK_SIZE != 0 ){
//
// throw( new Exception( "data must start at a block offset" ));
// }
//
// int piece_length = disk_mgr.getPieceLength();
//
// int data_length = 0;
//
// for( DirectByteBuffer buffer: data ){
//
// data_length += buffer.remaining( DirectByteBuffer.SS_DW );
// }
//
// long written = 0;
//
// int buffer_number = 0;
//
// for ( int i=0;i<data_length;i+=DiskManager.BLOCK_SIZE ){
//
// int rem = data_length - i;
//
// if ( rem > DiskManager.BLOCK_SIZE ){
//
// rem = DiskManager.BLOCK_SIZE;
// }
//
// int piece_number = (int)( data_offset / piece_length );
//
// DiskManagerPiece dm_piece = dm_pieces[piece_number];
//
// int block_number = (int)(data_offset - ( piece_number * piece_length )) / DiskManager.BLOCK_SIZE;
//
// int block_size = dm_piece.getBlockSize( block_number );
//
// if ( rem < block_size ){
//
// break;
// }
//
// DirectByteBuffer chunk = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_BT_PIECE, block_size );
//
//
// writeBlock( piece_number, block_number*DiskManager.BLOCK_SIZE, chunk, null, true );
//
// written += rem;
// data_offset += rem;
// }
//
// List<DirectByteBuffer> unwritten = new ArrayList<DirectByteBuffer>();
//
// for (int i=buffer_number;i<data.length;i++){
//
// if (data[i].hasRemaining( DirectByteBuffer.SS_DW )){
//
// unwritten.add( data[i] );
//
// }else{
//
// data[i].returnToPool();
// }
// }
//
// return( unwritten.toArray( new DirectByteBuffer[ unwritten.size()] ));
// }
//
//
// /** This method will queue up a dism manager write request for the block if the block is not already written.
// * It will send out cancels for the block to all peer either if in end-game mode, or per cancel param
// * @param pieceNumber to potentialy write to
// * @param offset within piece to queue write for
// * @param data to be writen
// * @param sender peer that sent this data
// * @param cancel if cancels definatly need to be sent to all peers for this request
// */
// public void writeBlock(int pieceNumber, int offset, DirectByteBuffer data, PEPeer sender, boolean cancel)
// {
// final int blockNumber =offset /DiskManager.BLOCK_SIZE;
// final DiskManagerPiece dmPiece =dm_pieces[pieceNumber];
// if (dmPiece.isWritten(blockNumber))
// {
// data.returnToPool();
// return;
// }
//
// PEPiece pe_piece = pePieces[ pieceNumber ];
//
// if ( pe_piece != null ){
//
// pe_piece.setDownloaded( offset );
// }
//
// final DiskManagerWriteRequest request =disk_mgr.createWriteRequest(pieceNumber, offset, data, sender);
// disk_mgr.enqueueWriteRequest(request, this );
// // In case we are in endGame mode, remove the block from the chunk list
// if (piecePicker.isInEndGameMode())
// piecePicker.removeFromEndGameModeChunks(pieceNumber, offset);
// if (cancel ||piecePicker.isInEndGameMode())
// { // cancel any matching outstanding download requests
// //For all connections cancel the request
// final ArrayList peer_transports = peer_transports_cow;
// for (int i=0;i<peer_transports.size();i++)
// {
// final PEPeerTransport connection =(PEPeerTransport) peer_transports.get(i);
// final DiskManagerReadRequest dmr =disk_mgr.createReadRequest(pieceNumber, offset, dmPiece.getBlockSize(blockNumber));
// connection.sendCancel( dmr );
// }
// }
// }
//
//
//// /**
//// * This method is only called when a block is received after the initial request expired,
//// * but the data has not yet been fulfilled by any other peer, so we use the block data anyway
//// * instead of throwing it away, and cancel any outstanding requests for that block that might have
//// * been sent after initial expiry.
//// */
//// public void writeBlockAndCancelOutstanding(int pieceNumber, int offset, DirectByteBuffer data,PEPeer sender) {
//// final int blockNumber =offset /DiskManager.BLOCK_SIZE;
//// final DiskManagerPiece dmPiece =dm_pieces[pieceNumber];
//// if (dmPiece.isWritten(blockNumber))
//// {
//// data.returnToPool();
//// return;
//// }
//// DiskManagerWriteRequest request =disk_mgr.createWriteRequest(pieceNumber, offset, data, sender);
//// disk_mgr.enqueueWriteRequest(request, this);
//
//// // cancel any matching outstanding download requests
//// List peer_transports =peer_transports_cow;
//// for (int i =0; i <peer_transports.size(); i++)
//// {
//// PEPeerTransport connection =(PEPeerTransport) peer_transports.get(i);
//// DiskManagerReadRequest dmr =disk_mgr.createReadRequest(pieceNumber, offset, dmPiece.getBlockSize(blockNumber));
//// connection.sendCancel(dmr);
//// }
//// }
//
//
// public boolean isWritten(int piece_number, int offset)
// {
// return dm_pieces[piece_number].isWritten(offset /DiskManager.BLOCK_SIZE);
// }
//
// public boolean
// validateReadRequest(
// PEPeerTransport originator,
// int pieceNumber,
// int offset,
// int length)
// {
// if ( disk_mgr.checkBlockConsistencyForRead(originator.getIp(),pieceNumber, offset, length)){
//
// if ( enable_seeding_piece_rechecks && isSeeding()){
//
// DiskManagerPiece dm_piece = dm_pieces[pieceNumber];
//
// int read_count = dm_piece.getReadCount()&0xffff;
//
// if ( read_count < SEED_CHECK_WAIT_MARKER - 1 ){
//
// read_count++;
//
// dm_piece.setReadCount((short)read_count );
// }
// }
//
// return( true );
// }else{
//
// return( false );
// }
// }
//
// public boolean
// validateHintRequest(
// PEPeerTransport originator,
// int pieceNumber,
// int offset,
// int length)
// {
// return( disk_mgr.checkBlockConsistencyForHint(originator.getIp(),pieceNumber, offset, length ));
// }
//
// public boolean
// validatePieceReply(
// PEPeerTransport originator,
// int pieceNumber,
// int offset,
// DirectByteBuffer data)
// {
// return disk_mgr.checkBlockConsistencyForWrite(originator.getIp(),pieceNumber, offset, data);
// }
//
// public int getAvailability(int pieceNumber)
// {
// return piecePicker.getAvailability(pieceNumber);
// }
//
// public void havePiece(int pieceNumber, int pieceLength, PEPeer pcOrigin) {
// piecePicker.addHavePiece(pcOrigin, pieceNumber);
// _stats.haveNewPiece(pieceLength);
//
// if(superSeedMode) {
// superSeedPieces[pieceNumber].peerHasPiece(pcOrigin);
// if(pieceNumber == pcOrigin.getUniqueAnnounce()) {
// pcOrigin.setUniqueAnnounce(-1);
// superSeedModeNumberOfAnnounces--;
// }
// }
// int availability =piecePicker.getAvailability(pieceNumber) -1;
// if (availability < 4) {
// if (dm_pieces[pieceNumber].isDone())
// availability--;
// if (availability <= 0)
// return;
// //for all peers
//
// final ArrayList peer_transports = peer_transports_cow;
//
// for (int i = peer_transports.size() - 1; i >= 0; i--) {
// final PEPeerTransport pc = (PEPeerTransport) peer_transports.get(i);
// if (pc !=pcOrigin &&pc.getPeerState() ==PEPeer.TRANSFERING &&pc.isPieceAvailable(pieceNumber))
// ((PEPeerStatsImpl)pc.getStats()).statisticalSentPiece(pieceLength / availability);
// }
// }
// }
//
// public int getPieceLength(int pieceNumber) {
//
// return disk_mgr.getPieceLength(pieceNumber);
//
// }
//
// public int
// getNbPeers()
// {
// return _peers;
// }
//
// public int getNbSeeds()
// {
// return _seeds;
// }
//
// public int getNbRemoteConnectionsExcludingUDP()
// {
// return _remotesNoUdpNoLan;
// }
//
// public long getLastRemoteConnectionTime()
// {
// return( last_remote_time );
// }
//
// public PEPeerManagerStats getStats() {
// return _stats;
// }
//
// public int
// getNbPeersStalledPendingLoad()
// {
// int res = 0;
//
// Iterator it = peer_transports_cow.iterator();
//
// while( it.hasNext()){
//
// PEPeerTransport transport = (PEPeerTransport)it.next();
//
// if ( transport.isStalledPendingLoad()){
//
// res ++;
// }
// }
//
// return( res );
// }
//
// /**
// * Returns the ETA time in seconds.
// * If the returned time is 0, the download is complete.
// * If the returned time is negative, the download
// * is complete and it took -xxx time to complete.
// */
// public long
// getETA()
// {
// final long now = SystemTime.getCurrentTime();
//
// if ( now < last_eta_calculation || now - last_eta_calculation > 900 ){
//
// long dataRemaining = disk_mgr.getRemainingExcludingDND();
//
// if ( dataRemaining > 0 ){
//
// int writtenNotChecked = 0;
//
// for (int i = 0; i < _nbPieces; i++)
// {
// if (dm_pieces[i].isInteresting()){
// writtenNotChecked +=dm_pieces[i].getNbWritten() *DiskManager.BLOCK_SIZE;
// }
// }
//
// dataRemaining = dataRemaining - writtenNotChecked;
//
// if (dataRemaining < 0 ){
// dataRemaining = 0;
// }
// }
//
// long result;
//
// if (dataRemaining == 0) {
// final long timeElapsed = (_timeFinished - _timeStarted)/1000;
// //if time was spent downloading....return the time as negative
// if(timeElapsed > 1){
// result = timeElapsed * -1;
// }else{
// result = 0;
// }
// }else{
//
// final long averageSpeed = _averageReceptionSpeed.getAverage();
// long lETA = (averageSpeed == 0) ? Constants.CRAPPY_INFINITE_AS_LONG : dataRemaining / averageSpeed;
// // stop the flickering of ETA from "Finished" to "x seconds" when we are
// // just about complete, but the data rate is jumpy.
// if (lETA == 0)
// lETA = 1;
// result = lETA;
// }
//
// last_eta = result;
// last_eta_calculation = now;
// }
//
// return( last_eta );
// }
//
// public boolean
// isRTA()
// {
// return( piecePicker.getRTAProviders().size() > 0 );
// }
//
// private void
// addToPeerTransports(
// PEPeerTransport peer )
// {
// boolean added = false;
//
// List limiters;
//
// try{
// peer_transports_mon.enter();
//
// // if it is already disconnected (synchronous failure during connect
// // for example) don't add it
//
// if ( peer.getPeerState() == PEPeer.DISCONNECTED ){
//
// return;
// }
//
// if( peer_transports_cow.contains( peer ) ){
// Debug.out( "Transport added twice" );
// return; //we do not want to close it
// }
//
// if( is_running ) {
// //copy-on-write semantics
// final ArrayList new_peer_transports = new ArrayList(peer_transports_cow.size() +1);
//
// new_peer_transports.addAll( peer_transports_cow );
//
// new_peer_transports.add( peer );
//
// peer_transports_cow = new_peer_transports;
//
// added = true;
// }
//
// limiters = external_rate_limiters_cow;
// }
// finally{
// peer_transports_mon.exit();
// }
//
// if( added ) {
// if ( peer.isIncoming()){
// long connect_time = SystemTime.getCurrentTime();
//
// if ( connect_time > last_remote_time ){
//
// last_remote_time = connect_time;
// }
// }
//
// if ( limiters != null ){
//
// for (int i=0;i<limiters.size();i++){
//
// Object[] entry = (Object[])limiters.get(i);
//
// peer.addRateLimiter((LimitedRateGroup)entry[0],((Boolean)entry[1]).booleanValue());
// }
// }
//
// peerAdded( peer );
// }
// else {
// peer.closeConnection( "PeerTransport added when manager not running" );
// }
// }
//
// public void
// addRateLimiter(
// LimitedRateGroup group,
// boolean upload )
// {
// List<PEPeer> transports;
//
// try{
// peer_transports_mon.enter();
//
// ArrayList<Object[]> new_limiters = new ArrayList<Object[]>( external_rate_limiters_cow==null?1:external_rate_limiters_cow.size()+1);
//
// if ( external_rate_limiters_cow != null ){
//
// new_limiters.addAll( external_rate_limiters_cow );
// }
//
// new_limiters.add( new Object[]{ group, new Boolean( upload )});
//
// external_rate_limiters_cow = new_limiters;
//
// transports = peer_transports_cow;
//
// }finally{
//
// peer_transports_mon.exit();
// }
//
// for (int i=0;i<transports.size();i++){
//
// transports.get(i).addRateLimiter( group, upload );
// }
// }
//
// public void
// removeRateLimiter(
// LimitedRateGroup group,
// boolean upload )
// {
// List transports;
//
// try{
// peer_transports_mon.enter();
//
// if ( external_rate_limiters_cow != null ){
//
// ArrayList new_limiters = new ArrayList( external_rate_limiters_cow.size()-1);
//
// for (int i=0;i<external_rate_limiters_cow.size();i++){
//
// Object[] entry = (Object[])external_rate_limiters_cow.get(i);
//
// if ( entry[0] != group ){
//
// new_limiters.add( entry );
// }
// }
//
// if ( new_limiters.size() == 0 ){
//
// external_rate_limiters_cow = null;
//
// }else{
//
// external_rate_limiters_cow = new_limiters;
// }
// }
//
// transports = peer_transports_cow;
//
// }finally{
//
// peer_transports_mon.exit();
// }
//
// for (int i=0;i<transports.size();i++){
//
// ((PEPeerTransport)transports.get(i)).removeRateLimiter( group, upload );
// }
// }
//
// public int
// getUploadRateLimitBytesPerSecond()
// {
// return( adapter.getUploadRateLimitBytesPerSecond());
// }
//
// public int
// getDownloadRateLimitBytesPerSecond()
// {
// return( adapter.getDownloadRateLimitBytesPerSecond());
// }
//
// // the peer calls this method itself in closeConnection() to notify this manager
//
// public void
// peerConnectionClosed(
// PEPeerTransport peer,
// boolean connect_failed,
// boolean network_failed )
// {
// boolean connection_found = false;
//
// boolean tcpReconnect = false;
// boolean ipv6reconnect = false;
//
// try{
// peer_transports_mon.enter();
//
// int udpPort = peer.getUDPListenPort();
//
// boolean canTryUDP = UDPNetworkManager.UDP_OUTGOING_ENABLED && peer.getUDPListenPort() > 0;
//// boolean canTryIpv6 = NetworkAdmin.getSingleton().hasIPV6Potential(true) && peer.getAlternativeIPv6() != null;
//
// if ( is_running ){
//
// PeerItem peer_item = peer.getPeerItemIdentity();
// PeerItem self_item = peer_database.getSelfPeer();
//
//
// if ( self_item == null || !self_item.equals( peer_item )){
//
// String ip = peer.getIp();
// boolean wasIPv6;
// try
// {
// wasIPv6 = InetAddress.getByName(ip) instanceof Inet6Address;
// } catch (UnknownHostException e)
// {
// wasIPv6 = false;
// // something is fishy about the old address, don't try to reconnect with v6
// canTryIpv6 = false;
// }
//
// //System.out.println("netfail="+network_failed+", connfail="+connect_failed+", can6="+canTryIpv6+", was6="+wasIPv6);
//
// String key = ip + ":" + udpPort;
//
// if ( peer.isTCP()){
//
// if ( connect_failed ){
//
// // TCP connect failure, try UDP later if necessary
//
// if ( canTryUDP && udp_fallback_for_failed_connection ){
//
// pending_nat_traversals.put(key, peer);
// } else if (canTryIpv6 && !wasIPv6)
// {
// tcpReconnect = true;
// ipv6reconnect = true;
// }
// }else if ( canTryUDP &&
// udp_fallback_for_dropped_connection &&
// network_failed &&
// seeding_mode &&
// peer.isInterested() &&
// !peer.isSeed() && !peer.isRelativeSeed() &&
// peer.getStats().getEstimatedSecondsToCompletion() > 60 &&
// FeatureAvailability.isUDPPeerReconnectEnabled()){
//
// if (Logger.isEnabled()){
// Logger.log(new LogEvent(peer, LOGID, LogEvent.LT_WARNING, "Unexpected stream closure detected, attempting recovery"));
// }
//
// // System.out.println( "Premature close of stream: " + getDisplayName() + "/" + peer.getIp());
//
// udp_reconnects.put( key, peer );
//
// }else if ( network_failed &&
// peer.isSafeForReconnect() &&
// !(seeding_mode && (peer.isSeed() || peer.isRelativeSeed() || peer.getStats().getEstimatedSecondsToCompletion() < 60)) &&
// getMaxConnections() > 0 &&
// getMaxNewConnectionsAllowed() > getMaxConnections() / 3 &&
// FeatureAvailability.isGeneralPeerReconnectEnabled()){
//
// tcpReconnect = true;
// }
// }else if ( connect_failed ){
//
// // UDP connect failure
//
// if ( udp_fallback_for_failed_connection ){
//
// if ( peer.getData(PEER_NAT_TRAVERSE_DONE_KEY) == null){
//
// // System.out.println( "Direct reconnect failed, attempting NAT traversal" );
//
// pending_nat_traversals.put(key, peer);
// }
// }
// }
// }
// }
//
// if( peer_transports_cow.contains( peer )) {
// final ArrayList new_peer_transports = new ArrayList( peer_transports_cow );
// new_peer_transports.remove(peer);
// peer_transports_cow = new_peer_transports;
// connection_found = true;
// }
// }
// finally{
// peer_transports_mon.exit();
// }
//
// if ( connection_found ){
// if( peer.getPeerState() != PEPeer.DISCONNECTED ) {
// System.out.println( "peer.getPeerState() != PEPeer.DISCONNECTED: " +peer.getPeerState() );
// }
//
// peerRemoved( peer ); //notify listeners
// }
//
// if(tcpReconnect)
// peer.reconnect(false, ipv6reconnect);
// }
//
//
//
//
// public void
// peerAdded(
// PEPeer pc)
// {
// adapter.addPeer(pc); //async downloadmanager notification
//
// //sync peermanager notification
// final ArrayList peer_manager_listeners = peer_manager_listeners_cow;
//
// for( int i=0; i < peer_manager_listeners.size(); i++ ) {
// ((PEPeerManagerListener)peer_manager_listeners.get(i)).peerAdded( this, pc );
// }
// }
//
//
// public void
// peerRemoved(
// PEPeer pc)
// {
// if ( is_running &&
// !seeding_mode &&
// ( prefer_udp || prefer_udp_default )){
//
// int udp = pc.getUDPListenPort();
//
// if ( udp != 0 && udp == pc.getTCPListenPort()){
//
// BloomFilter filter = prefer_udp_bloom;
//
// if ( filter == null ){
//
// filter = prefer_udp_bloom = BloomFilterFactory.createAddOnly( PREFER_UDP_BLOOM_SIZE );
// }
//
// if ( filter.getEntryCount() < PREFER_UDP_BLOOM_SIZE / 10 ){
//
// filter.add( pc.getIp().getBytes());
// }
// }
// }
//
// final int piece = pc.getUniqueAnnounce();
// if(piece != -1 && superSeedMode ) {
// superSeedModeNumberOfAnnounces--;
// superSeedPieces[piece].peerLeft();
// }
//
// int reserved_piece = pc.getReservedPieceNumber();
//
// if ( reserved_piece >= 0 ){
//
// PEPiece pe_piece = pePieces[reserved_piece];
//
// if ( pe_piece != null ){
//
// String reserved_by = pe_piece.getReservedBy();
//
// if ( reserved_by != null && reserved_by.equals( pc.getIp())){
//
// pe_piece.setReservedBy( null );
// }
// }
// }
//
// adapter.removePeer(pc); //async downloadmanager notification
//
// //sync peermanager notification
// final ArrayList peer_manager_listeners = peer_manager_listeners_cow;
//
// for( int i=0; i < peer_manager_listeners.size(); i++ ) {
// ((PEPeerManagerListener)peer_manager_listeners.get(i)).peerRemoved( this, pc );
// }
// }
//
// /** Don't pass a null to this method. All activations of pieces must go through here.
// * @param piece PEPiece invoked; notifications of it's invocation need to be done
// * @param pieceNumber of the PEPiece
// */
// public void addPiece(final PEPiece piece, final int pieceNumber)
// {
// addPiece( piece, pieceNumber, false );
// }
//
// protected void addPiece(final PEPiece piece, final int pieceNumber, final boolean force_add )
// {
// pePieces[pieceNumber] =(PEPieceImpl)piece;
// nbPiecesActive++;
// if ( is_running || force_add ){
// // deal with possible piece addition by scheduler loop after closdown started
// adapter.addPiece(piece);
// }
// }
//
// /** Sends messages to listeners that the piece is no longer active. All closing
// * out (deactivation) of pieces must go through here. The piece will be null upon return.
// * @param pePiece PEPiece to remove
// * @param pieceNumber int
// */
// public void removePiece(PEPiece pePiece, int pieceNumber) {
// if ( pePiece != null ){
// adapter.removePiece(pePiece);
// }
// pePieces[pieceNumber] =null;
// nbPiecesActive--;
// }
//
// public int getNbActivePieces()
// {
// return nbPiecesActive;
// }
//
// public String getElapsedTime() {
// return TimeFormatter.format((SystemTime.getCurrentTime() - _timeStarted) / 1000);
// }
//
//// Returns time started in ms
// public long getTimeStarted() {
// return _timeStarted;
// }
//
// public long getTimeStartedSeeding() {
// return _timeStartedSeeding;
// }
//
// private byte[] computeMd5Hash(DirectByteBuffer buffer)
// {
// BrokenMd5Hasher md5 = new BrokenMd5Hasher();
//
// md5.reset();
// final int position = buffer.position(DirectByteBuffer.SS_DW);
// md5.update(buffer.getBuffer(DirectByteBuffer.SS_DW));
// buffer.position(DirectByteBuffer.SS_DW, position);
// ByteBuffer md5Result = ByteBuffer.allocate(16);
// md5Result.position(0);
// md5.finalDigest( md5Result );
//
// final byte[] result =new byte[16];
// md5Result.position(0);
// for (int i =0; i <result.length; i++ )
// {
// result[i] = md5Result.get();
// }
//
// return result;
// }
//
// private void MD5CheckPiece(PEPiece piece, boolean correct)
// {
// final String[] writers =piece.getWriters();
// int offset = 0;
// for (int i =0; i <writers.length; i++ )
// {
// final int length =piece.getBlockSize(i);
// final String peer =writers[i];
// if (peer !=null)
// {
// DirectByteBuffer buffer =disk_mgr.readBlock(piece.getPieceNumber(), offset, length);
//
// if (buffer !=null)
// {
// final byte[] hash =computeMd5Hash(buffer);
// buffer.returnToPool();
// buffer = null;
// piece.addWrite(i,peer,hash,correct);
// }
// }
// offset += length;
// }
// }
//
// public void checkCompleted(DiskManagerCheckRequest request, boolean passed)
// {
// try
// {
// piece_check_result_list_mon.enter();
//
// piece_check_result_list.add(new Object[]{request, new Integer( passed?1:0 )});
// } finally
// {
// piece_check_result_list_mon.exit();
// }
// }
//
// public void checkCancelled(DiskManagerCheckRequest request)
// {
// try
// {
// piece_check_result_list_mon.enter();
//
// piece_check_result_list.add(new Object[]{request, new Integer( 2 )});
//
// } finally
// {
// piece_check_result_list_mon.exit();
// }
// }
//
// public void checkFailed(DiskManagerCheckRequest request, Throwable cause)
// {
// try
// {
// piece_check_result_list_mon.enter();
//
// piece_check_result_list.add(new Object[]{request, new Integer( 0 )});
//
// } finally
// {
// piece_check_result_list_mon.exit();
// }
// }
//
// public boolean needsMD5CheckOnCompletion(int pieceNumber)
// {
// final PEPieceImpl piece = pePieces[pieceNumber];
// if(piece == null)
// return false;
// return piece.getPieceWrites().size() > 0;
// }
//
// private void processPieceCheckResult(DiskManagerCheckRequest request, int outcome)
// {
// final int check_type =((Integer) request.getUserData()).intValue();
//
// try{
//
// final int pieceNumber =request.getPieceNumber();
//
// // System.out.println( "processPieceCheckResult(" + _finished + "/" + recheck_on_completion + "):" + pieceNumber +
// // "/" + piece + " - " + result );
//
// // passed = 1, failed = 0, cancelled = 2
//
// if (check_type ==CHECK_REASON_COMPLETE){
// // this is a recheck, so don't send HAVE msgs
//
// if ( outcome == 0 ){
//
// // piece failed; restart the download afresh
// Debug.out(getDisplayName() + ": Piece #" +pieceNumber +" failed final re-check. Re-downloading...");
//
// if (!restart_initiated){
//
// restart_initiated = true;
// adapter.restartDownload(true);
// }
// }
//
// return;
//
// }else if ( check_type == CHECK_REASON_SEEDING_CHECK || check_type == CHECK_REASON_BAD_PIECE_CHECK ){
//
// if ( outcome == 0 ){
//
// if ( check_type == CHECK_REASON_SEEDING_CHECK ){
//
// Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed recheck while seeding. Re-downloading...");
//
// }else{
//
// Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed recheck after being reported as bad. Re-downloading...");
// }
//
// Logger.log(new LogAlert(this, LogAlert.REPEATABLE, LogAlert.AT_ERROR,
// "Download '" + getDisplayName() + "': piece " + pieceNumber
// + " has been corrupted, re-downloading"));
//
// if ( !restart_initiated ){
//
// restart_initiated = true;
//
// adapter.restartDownload(true);
// }
// }
//
// return;
// }
//
// // piece can be null when running a recheck on completion
// // actually, give the above code I don't think this is true anymore...
//
// final PEPieceImpl pePiece =pePieces[pieceNumber];
//
// if ( outcome == 1 ){
//
// // the piece has been written correctly
//
// try{
// if (pePiece !=null){
//
// if (needsMD5CheckOnCompletion(pieceNumber)){
// MD5CheckPiece(pePiece, true);
// }
//
// final List list =pePiece.getPieceWrites();
//
// if (list.size() >0 ){
//
// //For each Block
// for (int i =0; i <pePiece.getNbBlocks(); i++ ){
//
// //System.out.println("Processing block " + i);
// //Find out the correct hash
// final List listPerBlock =pePiece.getPieceWrites(i);
// byte[] correctHash = null;
// //PEPeer correctSender = null;
// Iterator iterPerBlock = listPerBlock.iterator();
// while (iterPerBlock.hasNext())
// {
// final PEPieceWriteImpl write =(PEPieceWriteImpl) iterPerBlock.next();
// if (write.isCorrect())
// {
// correctHash = write.getHash();
// //correctSender = write.getSender();
// }
// }
// //System.out.println("Correct Hash " + correctHash);
// //If it's found
// if (correctHash !=null)
// {
// iterPerBlock = listPerBlock.iterator();
// while (iterPerBlock.hasNext())
// {
// final PEPieceWriteImpl write =(PEPieceWriteImpl) iterPerBlock.next();
// if (!Arrays.equals(write.getHash(), correctHash))
// {
// //Bad peer found here
// badPeerDetected(write.getSender(),pieceNumber);
// }
// }
// }
// }
// }
// }
// }finally{
// // regardless of any possible failure above, tidy up correctly
//
// removePiece(pePiece, pieceNumber);
//
// // send all clients a have message
// sendHave(pieceNumber); //XXX: if Done isn't set yet, might refuse to send this piece
// }
// }else if ( outcome == 0 ){
//
// // the piece is corrupt
//
// if ( pePiece != null ){
//
// try{
// MD5CheckPiece(pePiece, false);
//
// final String[] writers =pePiece.getWriters();
// final List uniqueWriters =new ArrayList();
// final int[] writesPerWriter =new int[writers.length];
// for (int i =0; i <writers.length; i++ )
// {
// final String writer =writers[i];
// if (writer !=null)
// {
// int writerId = uniqueWriters.indexOf(writer);
// if (writerId ==-1)
// {
// uniqueWriters.add(writer);
// writerId = uniqueWriters.size() - 1;
// }
// writesPerWriter[writerId]++;
// }
// }
// final int nbWriters =uniqueWriters.size();
// if (nbWriters ==1)
// {
// //Very simple case, only 1 peer contributed for that piece,
// //so, let's mark it as a bad peer
//
// String bad_ip = (String)uniqueWriters.get(0);
//
// PEPeerTransport bad_peer = getTransportFromAddress( bad_ip );
//
// if ( bad_peer != null ){
//
// bad_peer.sendBadPiece( pieceNumber );
// }
//
// badPeerDetected( bad_ip, pieceNumber);
//
// //and let's reset the whole piece
// pePiece.reset();
//
// }else if ( nbWriters > 1 ){
//
// int maxWrites = 0;
// String bestWriter =null;
//
// PEPeerTransport bestWriter_transport = null;
//
// for (int i =0; i <uniqueWriters.size(); i++ ){
//
// final int writes =writesPerWriter[i];
//
// if (writes > maxWrites ){
//
// final String writer =(String) uniqueWriters.get(i);
//
// PEPeerTransport pt =getTransportFromAddress(writer);
//
// if ( pt !=null &&
// pt.getReservedPieceNumber() ==-1 &&
// !ip_filter.isInRange(writer, getDisplayName(),getTorrentHash())){
//
// bestWriter = writer;
// maxWrites = writes;
//
// bestWriter_transport = pt;
// }
// }
// }
//
// if ( bestWriter !=null ){
//
// pePiece.setReservedBy(bestWriter);
//
// bestWriter_transport.setReservedPieceNumber(pePiece.getPieceNumber());
//
// pePiece.setRequestable();
//
// for (int i =0; i <pePiece.getNbBlocks(); i++ ){
//
// // If the block was contributed by someone else
//
// if (writers[i] == null ||!writers[i].equals( bestWriter )){
//
// pePiece.reDownloadBlock(i);
// }
// }
// }else{
//
// //In all cases, reset the piece
// pePiece.reset();
// }
// }else{
//
// //In all cases, reset the piece
// pePiece.reset();
// }
//
//
// //if we are in end-game mode, we need to re-add all the piece chunks
// //to the list of chunks needing to be downloaded
// piecePicker.addEndGameChunks(pePiece);
// _stats.hashFailed(pePiece.getLength());
//
// }catch( Throwable e ){
//
// Debug.printStackTrace(e);
//
// // anything craps out in the above code, ensure we tidy up
//
// pePiece.reset();
// }
// }else{
//
// // no active piece for some reason, clear down DM piece anyway
//
// Debug.out(getDisplayName() + "Piece #" +pieceNumber +" failed check and no active piece, resetting..." );
//
// dm_pieces[pieceNumber].reset();
// }
// }else{
//
// // cancelled, download stopped
// }
// }finally{
//
// if (check_type ==CHECK_REASON_SCAN ){
// rescan_piece_time = SystemTime.getCurrentTime();
// }
//
// if (!seeding_mode ){
// checkFinished( false );
// }
// }
// }
//
//
// private void badPeerDetected(String ip, int piece_number )
// {
// boolean hash_fail = piece_number >= 0;
//
// // note that peer can be NULL but things still work in the main
//
// PEPeerTransport peer = getTransportFromAddress(ip);
//
// if ( hash_fail && peer != null ){
//
// Iterator<PEPeerManagerListener> it = peer_manager_listeners_cow.iterator();
//
// while( it.hasNext()){
//
// try{
// it.next().peerSentBadData( this, peer, piece_number );
//
// }catch( Throwable e ){
//
// Debug.printStackTrace(e);
// }
// }
// }
// // Debug.out("Bad Peer Detected: " + peerIP + " [" + peer.getClient() + "]");
//
// IpFilterManager filter_manager =IpFilterManagerFactory.getSingleton();
//
// //Ban fist to avoid a fast reco of the bad peer
//
// int nbWarnings = filter_manager.getBadIps().addWarningForIp(ip);
//
// boolean disconnect_peer = false;
//
// // no need to reset the bad chunk count as the peer is going to be disconnected and
// // if it comes back it'll start afresh
//
// // warning limit only applies to hash-fails, discards cause immediate action
//
// if ( nbWarnings > WARNINGS_LIMIT ){
//
// if (COConfigurationManager.getBooleanParameter("Ip Filter Enable Banning")){
//
// // if a block-ban occurred, check other connections
//
// if (ip_filter.ban(ip, getDisplayName(), false )){
//
// checkForBannedConnections();
// }
//
// // Trace the ban
// if (Logger.isEnabled()){
// Logger.log(new LogEvent(peer, LOGID, LogEvent.LT_ERROR, ip +" : has been banned and won't be able "
// +"to connect until you restart azureus"));
// }
//
// disconnect_peer = true;
// }
// }else if ( !hash_fail ){
//
// // for failures due to excessive discard we boot the peer anyway
//
// disconnect_peer = true;
//
// }
//
// if ( disconnect_peer ){
//
// if ( peer != null ){
//
// final int ps =peer.getPeerState();
//
// // might have been through here very recently and already started closing
// // the peer (due to multiple bad blocks being found from same peer when checking piece)
// if (!(ps ==PEPeer.CLOSING ||ps ==PEPeer.DISCONNECTED))
// {
// // Close connection
// closeAndRemovePeer(peer, "has sent too many " + (hash_fail?"bad pieces":"discarded blocks") + ", " +WARNINGS_LIMIT +" max.", true);
// }
// }
// }
// }
//
// public PEPiece[] getPieces()
// {
// return pePieces;
// }
//
// public PEPiece getPiece(int pieceNumber)
// {
// return pePieces[pieceNumber];
// }
//
// public PEPeerStats
// createPeerStats(
// PEPeer owner )
// {
// return( new PEPeerStatsImpl( owner ));
// }
//
//
// public DiskManagerReadRequest
// createDiskManagerRequest(
// int pieceNumber,
// int offset,
// int length )
// {
// return( disk_mgr.createReadRequest( pieceNumber, offset, length ));
// }
//
// public boolean
// requestExists(
// String peer_ip,
// int piece_number,
// int offset,
// int length )
// {
// ArrayList peer_transports = peer_transports_cow;
//
// DiskManagerReadRequest request = null;
//
// for (int i=0; i < peer_transports.size(); i++) {
//
// PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
//
// if ( conn.getIp().equals( peer_ip )){
//
// if ( request == null ){
//
// request = createDiskManagerRequest( piece_number, offset, length );
// }
//
// if ( conn.getRequestIndex( request ) != -1 ){
//
// return( true );
// }
// }
// }
//
// return( false );
// }
//
// public boolean
// seedPieceRecheck()
// {
// if ( !( enable_seeding_piece_rechecks || isSeeding())){
//
// return( false );
// }
//
// int max_reads = 0;
// int max_reads_index = 0;
//
// for (int i=0;i<dm_pieces.length;i++){
//
// // skip dnd pieces
//
// DiskManagerPiece dm_piece = dm_pieces[i];
//
// if ( !dm_piece.isDone()){
//
// continue;
// }
//
// int num = dm_piece.getReadCount()&0xffff;
//
// if ( num > SEED_CHECK_WAIT_MARKER ){
//
// // recently been checked, skip for a while
//
// num--;
//
// if ( num == SEED_CHECK_WAIT_MARKER ){
//
// num = 0;
// }
//
// dm_piece.setReadCount((short)num);
//
// }else{
//
// if ( num > max_reads ){
//
// max_reads = num;
// max_reads_index = i;
// }
// }
// }
//
// if ( max_reads > 0 ){
//
// DiskManagerPiece dm_piece = dm_pieces[ max_reads_index ];
//
// // if the piece has been read 3 times (well, assuming each block is read once,
// // which is obviously wrong, but...)
//
// if ( max_reads >= dm_piece.getNbBlocks() * 3 ){
//
// DiskManagerCheckRequest req = disk_mgr.createCheckRequest( max_reads_index, new Integer( CHECK_REASON_SEEDING_CHECK ) );
//
// req.setAdHoc( true );
//
// req.setLowPriority( true );
//
// if (Logger.isEnabled())
// Logger.log(new LogEvent(disk_mgr.getTorrent(), LOGID,
// "Rechecking piece " + max_reads_index + " while seeding as most active"));
//
// disk_mgr.enqueueCheckRequest( req, this );
//
// dm_piece.setReadCount((short)65535);
//
// // clear out existing, non delayed pieces so we start counting piece activity
// // again
//
// for (int i=0;i<dm_pieces.length;i++){
//
// if ( i != max_reads_index ){
//
// int num = dm_pieces[i].getReadCount()&0xffff;
//
// if ( num < SEED_CHECK_WAIT_MARKER ){
//
// dm_pieces[i].setReadCount((short)0 );
// }
// }
// }
//
// return( true );
// }
// }
//
// return( false );
// }
//
// public void
// addListener(
// PEPeerManagerListener l )
// {
// try{
// this_mon.enter();
//
// //copy on write
// final ArrayList peer_manager_listeners = new ArrayList( peer_manager_listeners_cow.size() + 1 );
// peer_manager_listeners.addAll( peer_manager_listeners_cow );
// peer_manager_listeners.add( l );
// peer_manager_listeners_cow = peer_manager_listeners;
//
// }finally{
//
// this_mon.exit();
// }
// }
//
// public void
// removeListener(
// PEPeerManagerListener l )
// {
// try{
// this_mon.enter();
//
// //copy on write
// final ArrayList peer_manager_listeners = new ArrayList( peer_manager_listeners_cow );
// peer_manager_listeners.remove( l );
// peer_manager_listeners_cow = peer_manager_listeners;
//
// }finally{
//
// this_mon.exit();
// }
// }
//
//
// public void
// parameterChanged(
// String parameterName)
// {
// if ( parameterName.equals("Ip Filter Enabled")){
//
// checkForBannedConnections();
// }
// }
//
// private void
// checkForBannedConnections()
// {
// if ( ip_filter.isEnabled()){ //if ipfiltering is enabled, remove any existing filtered connections
// ArrayList to_close = null;
//
// final ArrayList peer_transports = peer_transports_cow;
//
// String name = getDisplayName();
// byte[] hash = getTorrentHash();
//
// for (int i=0; i < peer_transports.size(); i++) {
// final PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
//
// if ( ip_filter.isInRange( conn.getIp(), name, hash )) {
// if( to_close == null ) to_close = new ArrayList();
// to_close.add( conn );
// }
// }
//
// if( to_close != null ) {
// for( int i=0; i < to_close.size(); i++ ) {
// closeAndRemovePeer( (PEPeerTransport)to_close.get(i), "IPFilter banned IP address", true );
// }
// }
// }
// }
//
// public boolean
// isSeeding()
// {
// return( seeding_mode );
// }
//
// public boolean isInEndGameMode() {
// return piecePicker.isInEndGameMode();
// }
//
// public boolean isSuperSeedMode() {
// return superSeedMode;
// }
//
// public boolean
// canToggleSuperSeedMode()
// {
// if ( superSeedMode ){
//
// return( true );
// }
//
// return( superSeedPieces == null && this.getRemaining() ==0 );
// }
//
// public void
// setSuperSeedMode(
// boolean _superSeedMode)
// {
// if ( _superSeedMode == superSeedMode ){
//
// return;
// }
//
// boolean kick_peers = false;
//
// if ( _superSeedMode ){
//
// if ( superSeedPieces == null && this.getRemaining() ==0 ){
//
// superSeedMode = true;
//
// initialiseSuperSeedMode();
//
// kick_peers = true;
// }
// }else{
//
// superSeedMode = false;
//
// kick_peers = true;
// }
//
// if ( kick_peers ){
//
// // turning on/off super-seeding, gotta kick all connected peers so they get the
// // "right" bitfield
//
// ArrayList peer_transports = peer_transports_cow;
//
// for (int i=0; i < peer_transports.size(); i++) {
//
// PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
//
// closeAndRemovePeer( conn, "Turning on super-seeding", false );
// }
// }
// }
//
// private void
// initialiseSuperSeedMode()
// {
// superSeedPieces = new SuperSeedPiece[_nbPieces];
// for(int i = 0 ; i < _nbPieces ; i++) {
// superSeedPieces[i] = new SuperSeedPiece(this,i);
// }
// }
//
// private void updatePeersInSuperSeedMode() {
// if(!superSeedMode) {
// return;
// }
//
// //Refresh the update time in case this is needed
// for(int i = 0 ; i < superSeedPieces.length ; i++) {
// superSeedPieces[i].updateTime();
// }
//
// //Use the same number of announces than unchoke
// int nbUnchoke = adapter.getMaxUploads();
// if(superSeedModeNumberOfAnnounces >= 2 * nbUnchoke)
// return;
//
//
// //Find an available Peer
// PEPeer selectedPeer = null;
// List sortedPeers = null;
//
// final ArrayList peer_transports = peer_transports_cow;
//
// sortedPeers = new ArrayList(peer_transports.size());
// Iterator iter = peer_transports.iterator();
// while(iter.hasNext()) {
// sortedPeers.add(new SuperSeedPeer((PEPeer)iter.next()));
// }
//
// Collections.sort(sortedPeers);
// iter = sortedPeers.iterator();
// while(iter.hasNext()) {
// final PEPeer peer = ((SuperSeedPeer)iter.next()).peer;
// if((peer.getUniqueAnnounce() == -1) && (peer.getPeerState() == PEPeer.TRANSFERING)) {
// selectedPeer = peer;
// break;
// }
// }
//
// if(selectedPeer == null ||selectedPeer.getPeerState() >=PEPeer.CLOSING)
// return;
//
// if(selectedPeer.getUploadHint() == 0) {
// //Set to infinite
// selectedPeer.setUploadHint(Constants.CRAPPY_INFINITY_AS_INT);
// }
//
// //Find a piece
// boolean found = false;
// SuperSeedPiece piece = null;
// while(!found) {
// piece = superSeedPieces[superSeedModeCurrentPiece];
// if(piece.getLevel() > 0) {
// piece = null;
// superSeedModeCurrentPiece++;
// if(superSeedModeCurrentPiece >= _nbPieces) {
// superSeedModeCurrentPiece = 0;
//
// //quit superseed mode
// superSeedMode = false;
// closeAndRemoveAllPeers( "quiting SuperSeed mode", true );
//
// return;
// }
// } else {
// found = true;
// }
// }
//
// if(piece == null) {
// return;
// }
//
// //If this peer already has this piece, return (shouldn't happen)
// if(selectedPeer.isPieceAvailable(piece.getPieceNumber())) {
// return;
// }
//
// selectedPeer.setUniqueAnnounce(piece.getPieceNumber());
// superSeedModeNumberOfAnnounces++;
// piece.pieceRevealedToPeer();
// ((PEPeerTransport)selectedPeer).sendHave(piece.getPieceNumber());
// }
//
// public void updateSuperSeedPiece(PEPeer peer,int pieceNumber) {
// if (!superSeedMode)
// return;
// superSeedPieces[pieceNumber].peerHasPiece(null);
// if(peer.getUniqueAnnounce() == pieceNumber)
// {
// peer.setUniqueAnnounce(-1);
// superSeedModeNumberOfAnnounces--;
// }
// }
//
// public boolean
// isExtendedMessagingEnabled()
// {
// return( adapter.isExtendedMessagingEnabled());
// }
//
// public boolean
// isPeerExchangeEnabled()
// {
// return( adapter.isPeerExchangeEnabled());
// }
//
// public LimitedRateGroup getUploadLimitedRateGroup() { return upload_limited_rate_group; }
//
// public LimitedRateGroup getDownloadLimitedRateGroup() { return download_limited_rate_group; }
//
//
// /** To retreive arbitrary objects against this object. */
// public Object
// getData(
// String key)
// {
// try{
// this_mon.enter();
//
// if (user_data == null) return null;
//
// return user_data.get(key);
//
// }finally{
//
// this_mon.exit();
// }
// }
//
// /** To store arbitrary objects against a control. */
//
// public void
// setData(
// String key,
// Object value)
// {
// try{
// this_mon.enter();
//
// if (user_data == null) {
// user_data = new HashMap();
// }
// if (value == null) {
// if (user_data.containsKey(key))
// user_data.remove(key);
// } else {
// user_data.put(key, value);
// }
// }finally{
// this_mon.exit();
// }
// }
//
//
// private void doConnectionChecks()
// {
// //every 1 second
// if ( mainloop_loop_count % MAINLOOP_ONE_SECOND_INTERVAL == 0 ){
// final ArrayList peer_transports = peer_transports_cow;
//
// int num_waiting_establishments = 0;
//
// int udp_connections = 0;
//
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
//
// //update waiting count
// final int state = transport.getConnectionState();
// if( state == PEPeerTransport.CONNECTION_PENDING || state == PEPeerTransport.CONNECTION_CONNECTING ) {
// num_waiting_establishments++;
// }
//
// if ( !transport.isTCP()){
//
// udp_connections++;
// }
// }
//
// int allowed_seeds = getMaxSeedConnections();
//
// if ( allowed_seeds > 0 ){
//
// int to_disconnect = _seeds - allowed_seeds;
//
// if ( to_disconnect > 0 ){
//
// // seeds are limited by people trying to get a reasonable upload by connecting
// // to leechers where possible. disconnect seeds from end of list to prevent
// // cycling of seeds
//
// for( int i=peer_transports.size()-1; i >= 0 && to_disconnect > 0; i-- ){
//
// final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
//
// if ( transport.isSeed()){
//
// closeAndRemovePeer( transport, "Too many seeds", false );
//
// to_disconnect--;
// }
// }
// }
// }
//
// //pass from storage to connector
// int allowed = getMaxNewConnectionsAllowed();
//
// if( allowed < 0 || allowed > 1000 ) allowed = 1000; //ensure a very upper limit so it doesnt get out of control when using PEX
//
// if( adapter.isNATHealthy()) { //if unfirewalled, leave slots avail for remote connections
// final int free = getMaxConnections() / 20; //leave 5%
// allowed = allowed - free;
// }
//
// if( allowed > 0 ) {
// //try and connect only as many as necessary
//
// final int wanted = TCPConnectionManager.MAX_SIMULTANIOUS_CONNECT_ATTEMPTS - num_waiting_establishments;
//
// if( wanted > allowed ) {
// num_waiting_establishments += wanted - allowed;
// }
//
// int remaining = allowed;
//
// int tcp_remaining = TCPNetworkManager.getSingleton().getConnectDisconnectManager().getMaxOutboundPermitted();
//
// int udp_remaining = UDPNetworkManager.getSingleton().getConnectionManager().getMaxOutboundPermitted();
//
// //load stored peer-infos to be established
// while( num_waiting_establishments < TCPConnectionManager.MAX_SIMULTANIOUS_CONNECT_ATTEMPTS && ( tcp_remaining > 0 || udp_remaining > 0 )){
// if( !is_running ) break;
//
// final PeerItem item = peer_database.getNextOptimisticConnectPeer();
//
// if( item == null || !is_running ) break;
//
// final PeerItem self = peer_database.getSelfPeer();
// if( self != null && self.equals( item ) ) {
// continue;
// }
//
// if( !isAlreadyConnected( item ) ) {
// final String source = PeerItem.convertSourceString( item.getSource() );
//
// final boolean use_crypto = item.getHandshakeType() == PeerItemFactory.HANDSHAKE_TYPE_CRYPTO;
//
// int tcp_port = item.getTCPPort();
// int udp_port = item.getUDPPort();
//
// if ( udp_port == 0 && udp_probe_enabled ){
//
// // for probing we assume udp port same as tcp
//
// udp_port = tcp_port;
// }
//
// boolean prefer_udp_overall = prefer_udp || prefer_udp_default;
//
// if ( prefer_udp_overall && udp_port == 0 ){
//
// // see if we have previous record of this address as udp connectable
//
// byte[] address = item.getIP().getBytes();
//
// BloomFilter bloom = prefer_udp_bloom;
//
// if ( bloom != null && bloom.contains( address )){
//
// udp_port = tcp_port;
// }
// }
//
// boolean tcp_ok = TCPNetworkManager.TCP_OUTGOING_ENABLED && tcp_port > 0 && tcp_remaining > 0;
// boolean udp_ok = UDPNetworkManager.UDP_OUTGOING_ENABLED && udp_port > 0 && udp_remaining > 0;
//
// if ( tcp_ok && !( prefer_udp_overall && udp_ok )){
//
// if ( makeNewOutgoingConnection( source, item.getAddressString(), tcp_port, udp_port, true, use_crypto, item.getCryptoLevel(), null) == null) {
//
// tcp_remaining--;
//
// num_waiting_establishments++;
// remaining--;
// }
// }else if ( udp_ok ){
//
// if ( makeNewOutgoingConnection( source, item.getAddressString(), tcp_port, udp_port, false, use_crypto, item.getCryptoLevel(), null) == null) {
//
// udp_remaining--;
//
// num_waiting_establishments++;
//
// remaining--;
// }
// }
// }
// }
//
// if ( UDPNetworkManager.UDP_OUTGOING_ENABLED &&
// remaining > 0 &&
// udp_remaining > 0 &&
// udp_connections < MAX_UDP_CONNECTIONS ){
//
// doUDPConnectionChecks( remaining );
// }
// }
// }
//
// //every 5 seconds
// if ( mainloop_loop_count % MAINLOOP_FIVE_SECOND_INTERVAL == 0 ) {
// final ArrayList peer_transports = peer_transports_cow;
//
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport transport = (PEPeerTransport)peer_transports.get( i );
//
// //check for timeouts
// if( transport.doTimeoutChecks() ) continue;
//
// //keep-alive check
// transport.doKeepAliveCheck();
//
// //speed tuning check
// transport.doPerformanceTuningCheck();
// }
// }
//
// // every 10 seconds check for connected + banned peers
// if ( mainloop_loop_count % MAINLOOP_TEN_SECOND_INTERVAL == 0 )
// {
// final long last_update = ip_filter.getLastUpdateTime();
// if ( last_update != ip_filter_last_update_time )
// {
// ip_filter_last_update_time = last_update;
// checkForBannedConnections();
// }
// }
//
// //every 30 seconds
// if ( mainloop_loop_count % MAINLOOP_THIRTY_SECOND_INTERVAL == 0 ) {
// //if we're at our connection limit, time out the least-useful
// //one so we can establish a possibly-better new connection
// optimisticDisconnectCount = 0;
// if( getMaxNewConnectionsAllowed() == 0 ) { //we've reached limit
// doOptimisticDisconnect( false, false );
// }
// }
//
//
// //sweep over all peers in a 60 second timespan
// float percentage = ((mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL) + 1F) / (1F *MAINLOOP_SIXTY_SECOND_INTERVAL);
// int goal;
// if(mainloop_loop_count % MAINLOOP_SIXTY_SECOND_INTERVAL == 0)
// {
// goal = 0;
// sweepList = peer_transports_cow;
// } else
// goal = (int)Math.floor(percentage * sweepList.size());
//
// for( int i=nextPEXSweepIndex; i < goal && i < sweepList.size(); i++) {
// //System.out.println(mainloop_loop_count+" %:"+percentage+" start:"+nextPEXSweepIndex+" current:"+i+" <"+goal+"/"+sweepList.size());
// final PEPeerTransport peer = (PEPeerTransport)sweepList.get( i );
// peer.updatePeerExchange();
// }
//
// nextPEXSweepIndex = goal;
// }
//
// private void
// doUDPConnectionChecks(
// int number )
// {
// List new_connections = null;
//
// try{
// peer_transports_mon.enter();
//
// long now = SystemTime.getCurrentTime();
//
// if ( udp_reconnects.size() > 0 && now - last_udp_reconnect >= UDP_RECONNECT_MIN_MILLIS ){
//
// last_udp_reconnect = now;
//
// Iterator it = udp_reconnects.values().iterator();
//
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// it.remove();
//
// if (Logger.isEnabled()){
// Logger.log(new LogEvent(this, LOGID, LogEvent.LT_INFORMATION, "Reconnecting to previous failed peer " + peer.getPeerItemIdentity().getAddressString()));
// }
//
// if ( new_connections == null ){
//
// new_connections = new ArrayList();
// }
//
// new_connections.add( peer );
//
// number--;
//
// if ( number <= 0 ){
//
// return;
// }
// }
//
// if ( pending_nat_traversals.size() == 0 ){
//
// return;
// }
//
// int max = MAX_UDP_TRAVERSAL_COUNT;
//
// // bigger the swarm, less chance of doing it
//
// if ( seeding_mode ){
//
// if ( _peers > 8 ){
//
// max = 0;
//
// }else{
//
// max = 1;
// }
// }else if ( _seeds > 8 ){
//
// max = 0;
//
// }else if ( _seeds > 4 ){
//
// max = 1;
// }
//
// int avail = max - udp_traversal_count;
//
// int to_do = Math.min( number, avail );
//
// Iterator it = pending_nat_traversals.values().iterator();
//
// while( to_do > 0 && it.hasNext()){
//
// to_do--;
//
// final PEPeerTransport peer = (PEPeerTransport)it.next();
//
// it.remove();
//
// PeerNATTraverser.getSingleton().create(
// this,
// new InetSocketAddress( peer.getPeerItemIdentity().getAddressString(), peer.getPeerItemIdentity().getUDPPort() ),
// new PeerNATTraversalAdapter()
// {
// private boolean done;
//
// public void
// success(
// InetSocketAddress target )
// {
// complete();
//
// PEPeerTransport newTransport = peer.reconnect(true, false);
//
// if( newTransport != null ){
//
// newTransport.setData(PEER_NAT_TRAVERSE_DONE_KEY, "");
// }
// }
//
// public void
// failed()
// {
// complete();
// }
//
// protected void
// complete()
// {
// try{
// peer_transports_mon.enter();
//
// if ( !done ){
//
// done = true;
//
// udp_traversal_count--;
// }
// }finally{
//
// peer_transports_mon.exit();
// }
// }
// });
//
// udp_traversal_count++;
// }
// }finally{
//
// peer_transports_mon.exit();
//
// if ( new_connections != null ){
//
// for (int i=0;i<new_connections.size();i++){
//
// PEPeerTransport peer_item = (PEPeerTransport)new_connections.get(i);
//
// // don't call when holding monitor - deadlock potential
// peer_item.reconnect(true, false);
//
// }
// }
// }
// }
//
// // counter is reset every 30s by doConnectionChecks()
// private int optimisticDisconnectCount = 0;
//
// public boolean doOptimisticDisconnect( boolean pending_lan_local_peer, boolean force )
// {
//
// final ArrayList peer_transports = peer_transports_cow;
// PEPeerTransport max_transport = null;
// PEPeerTransport max_seed_transport = null;
// PEPeerTransport max_non_lan_transport = null;
//
// long max_time = 0;
// long max_seed_time = 0;
// long max_non_lan_time = 0;
//
//
// List<Long> activeConnectionTimes = new ArrayList<Long>(peer_transports.size());
//
// int lan_peer_count = 0;
//
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
//
// if( peer.getConnectionState() == PEPeerTransport.CONNECTION_FULLY_ESTABLISHED ) {
//
// final long timeSinceConnection =peer.getTimeSinceConnectionEstablished();
// final long timeSinceSentData =peer.getTimeSinceLastDataMessageSent();
//
// activeConnectionTimes.add(timeSinceConnection);
//
// long peerTestTime = 0;
// if( seeding_mode){
// if( timeSinceSentData != -1 )
// peerTestTime = timeSinceSentData; //ensure we've sent them at least one data message to qualify for drop
// }else{
// final long timeSinceGoodData =peer.getTimeSinceGoodDataReceived();
//
//
// if( timeSinceGoodData == -1 )
// peerTestTime +=timeSinceConnection; //never received
// else
// peerTestTime +=timeSinceGoodData;
//
// // try to drop unInteresting in favor of Interesting connections
// if (!peer.isInteresting())
// {
// if (!peer.isInterested()) // if mutually unInterested, really try to drop the connection
// peerTestTime +=timeSinceConnection +timeSinceSentData; // if we never sent, it will subtract 1, which is good
// else
// peerTestTime +=(timeSinceConnection -timeSinceSentData); // try to give interested peers a chance to get data
//
// peerTestTime *=2;
// }
//
// peerTestTime +=peer.getSnubbedTime();
// }
//
// if( !peer.isIncoming() ){
// peerTestTime = peerTestTime * 2; //prefer to drop a local connection, to make room for more remotes
// }
//
// if ( peer.isLANLocal()){
//
// lan_peer_count++;
//
// }else{
//
// if( peerTestTime > max_non_lan_time ) {
// max_non_lan_time = peerTestTime;
// max_non_lan_transport = peer;
// }
// }
//
//
//
// // anti-leech checks
// if( !seeding_mode ) {
//
// // remove long-term snubbed peers with higher probability
// peerTestTime += peer.getSnubbedTime();
// if(peer.getSnubbedTime() > 2*60) {peerTestTime*=1.5;}
//
// PEPeerStats pestats = peer.getStats();
// // everybody has deserverd a chance of half an MB transferred data
// if(pestats.getTotalDataBytesReceived()+pestats.getTotalDataBytesSent() > 1024*512 ) {
// boolean goodPeer = true;
//
// // we don't like snubbed peers with a negative gain
// if( peer.isSnubbed() && pestats.getTotalDataBytesReceived() < pestats.getTotalDataBytesSent() ) {
// peerTestTime *= 1.5;
// goodPeer = false;
// }
// // we don't like peers with a very bad ratio (10:1)
// if( pestats.getTotalDataBytesSent() > pestats.getTotalDataBytesReceived() * 10 ) {
// peerTestTime *= 2;
// goodPeer = false;
// }
// // modify based on discarded : overall downloaded ratio
// if( pestats.getTotalDataBytesReceived() > 0 && pestats.getTotalBytesDiscarded() > 0 ) {
// peerTestTime = (long)(peerTestTime *( 1.0+((double)pestats.getTotalBytesDiscarded()/(double)pestats.getTotalDataBytesReceived())));
// }
//
// // prefer peers that do some work, let the churn happen with peers that did nothing
// if(goodPeer)
// peerTestTime *= 0.7;
// }
// }
//
//
// if( peerTestTime > max_time ) {
// max_time = peerTestTime;
// max_transport = peer;
// }
//
// if ( peer.isSeed() || peer.isRelativeSeed()){
//
// if( peerTestTime > max_seed_time ) {
// max_seed_time = peerTestTime;
// max_seed_transport = peer;
// }
// }
// }
// }
//
// long medianConnectionTime;
//
// if ( activeConnectionTimes.size() > 0 ){
// Collections.sort(activeConnectionTimes);
// medianConnectionTime = activeConnectionTimes.get(activeConnectionTimes.size()/2);
// }else{
// medianConnectionTime = 0;
// }
//
// // allow 1 disconnect every 30s per 30 peers; 2 at least every 30s
// int maxOptimistics = Math.max(getMaxConnections()/30,2);
//
// // avoid unnecessary churn, e.g.
// if(!pending_lan_local_peer && !force && optimisticDisconnectCount >= maxOptimistics && medianConnectionTime < 5*60*1000)
// return false;
//
//
// // don't boot lan peers if we can help it (unless we have a few of them)
//
// if ( max_transport != null ){
//
// final int LAN_PEER_MAX = 4;
//
// if ( max_transport.isLANLocal() && lan_peer_count < LAN_PEER_MAX && max_non_lan_transport != null ){
//
// // override lan local max with non-lan local max
//
// max_transport = max_non_lan_transport;
// max_time = max_non_lan_time;
// }
//
// // if we have a seed limit, kick seeds in preference to non-seeds
//
// if( getMaxSeedConnections() > 0 && max_seed_transport != null && max_time > 5*60*1000 ) {
// closeAndRemovePeer( max_seed_transport, "timed out by doOptimisticDisconnect()", true );
// optimisticDisconnectCount++;
// return true;
// }
//
// if( max_transport != null && max_time > 5 *60*1000 ) { //ensure a 5 min minimum test time
// closeAndRemovePeer( max_transport, "timed out by doOptimisticDisconnect()", true );
// optimisticDisconnectCount++;
// return true;
// }
//
// // kick worst peers to accomodate lan peer
//
// if ( pending_lan_local_peer && lan_peer_count < LAN_PEER_MAX ){
// closeAndRemovePeer( max_transport, "making space for LAN peer in doOptimisticDisconnect()", true );
// optimisticDisconnectCount++;
// return true;
// }
//
// if ( force ){
//
// closeAndRemovePeer( max_transport, "force removal of worst peer in doOptimisticDisconnect()", true );
//
// return true;
// }
// }else if ( force ){
//
// if ( peer_transports.size() > 0 ){
//
// PEPeerTransport pt = (PEPeerTransport)peer_transports.get( new Random().nextInt( peer_transports.size()));
//
// closeAndRemovePeer( pt, "force removal of random peer in doOptimisticDisconnect()", true );
//
// return true;
// }
// }
//
// return false;
// }
//
//
// public PeerExchangerItem createPeerExchangeConnection( final PEPeerTransport base_peer ) {
// if( base_peer.getTCPListenPort() > 0 ) { //only accept peers whose remote port is known
// final PeerItem peer =
// PeerItemFactory.createPeerItem( base_peer.getIp(),
// base_peer.getTCPListenPort(),
// PeerItemFactory.PEER_SOURCE_PEER_EXCHANGE,
// base_peer.getPeerItemIdentity().getHandshakeType(),
// base_peer.getUDPListenPort(),
// PeerItemFactory.CRYPTO_LEVEL_1,
// 0 );
//
// return peer_database.registerPeerConnection( peer, new PeerExchangerItem.Helper(){
// public boolean
// isSeed()
// {
// return base_peer.isSeed();
// }
// });
// }
//
// return null;
// }
//
//
//
// private boolean isAlreadyConnected( PeerItem peer_id ) {
// final ArrayList peer_transports = peer_transports_cow;
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport peer = (PEPeerTransport)peer_transports.get( i );
// if( peer.getPeerItemIdentity().equals( peer_id ) ) return true;
// }
// return false;
// }
//
//
// public void peerVerifiedAsSelf( PEPeerTransport self ) {
// if( self.getTCPListenPort() > 0 ) { //only accept self if remote port is known
// final PeerItem peer = PeerItemFactory.createPeerItem( self.getIp(), self.getTCPListenPort(),
// PeerItem.convertSourceID( self.getPeerSource() ), self.getPeerItemIdentity().getHandshakeType(), self.getUDPListenPort(),PeerItemFactory.CRYPTO_LEVEL_CURRENT, 0 );
// peer_database.setSelfPeer( peer );
// }
// }
//
// public boolean
// canIPBeBanned(
// String ip )
// {
// return true;
// }
//
// public boolean
// canIPBeBlocked(
// String ip,
// byte[] torrent_hash )
// {
// return true;
// }
//
// public long
// getHiddenBytes()
// {
// if ( hidden_piece < 0 ){
//
// return( 0 );
// }
//
// return( dm_pieces[hidden_piece].getLength());
// }
//
// public int
// getHiddenPiece()
// {
// return( hidden_piece );
// }
//
// public void IPBlockedListChanged(IpFilter filter) {
// Iterator it = peer_transports_cow.iterator();
//
// String name = getDisplayName();
// byte[] hash = getTorrentHash();
//
// while( it.hasNext()){
// try {
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// if (filter.isInRange(peer.getIp(), name, hash )) {
// peer.closeConnection( "IP address blocked by filters" );
// }
// } catch (Exception e) {
// }
// }
// }
//
// public void IPBanned(BannedIp ip)
// {
// for (int i =0; i <_nbPieces; i++ )
// {
// if (pePieces[i] !=null)
// pePieces[i].reDownloadBlocks(ip.getIp());
// }
// }
//
//
// public int getAverageCompletionInThousandNotation()
// {
// final ArrayList peer_transports = peer_transports_cow;
//
// if (peer_transports !=null)
// {
// final long total =disk_mgr.getTotalLength();
//
// final int my_completion = total == 0
// ? 1000
// : (int) ((1000 * (total - disk_mgr.getRemainingExcludingDND())) / total);
//
// int sum = my_completion == 1000 ? 0 : my_completion; //add in our own percentage if not seeding
// int num = my_completion == 1000 ? 0 : 1;
//
// for (int i =0; i <peer_transports.size(); i++ )
// {
// final PEPeer peer =(PEPeer) peer_transports.get(i);
//
// if (peer.getPeerState() ==PEPeer.TRANSFERING &&!peer.isSeed())
// {
// num++;
// sum += peer.getPercentDoneInThousandNotation();
// }
// }
//
// return num > 0 ? sum / num : 0;
// }
//
// return -1;
// }
//
// public int
// getMaxConnections()
// {
// return( adapter.getMaxConnections());
// }
//
// public int
// getMaxSeedConnections()
// {
// return( adapter.getMaxSeedConnections());
// }
//
// public int
// getMaxNewConnectionsAllowed()
// {
// final int dl_max = getMaxConnections();
//
// final int allowed_peers = PeerUtils.numNewConnectionsAllowed(getPeerIdentityDataID(), dl_max );
//
// return( allowed_peers );
// }
//
// public int getSchedulePriority() {
// return isSeeding() ? Integer.MAX_VALUE : adapter.getPosition();
// }
//
// public boolean
// hasPotentialConnections()
// {
// return( pending_nat_traversals.size() + peer_database.getDiscoveredPeerCount() > 0 );
// }
//
// public String
// getRelationText()
// {
// return( adapter.getLogRelation().getRelationText());
// }
//
// public Object[]
// getQueryableInterfaces()
// {
// return( adapter.getLogRelation().getQueryableInterfaces());
// }
//
//
//
// public PEPeerTransport getTransportFromIdentity( byte[] peer_id ) {
// final ArrayList peer_transports = peer_transports_cow;
// for( int i=0; i < peer_transports.size(); i++ ) {
// final PEPeerTransport conn = (PEPeerTransport)peer_transports.get( i );
// if( Arrays.equals( peer_id, conn.getId() ) ) return conn;
// }
// return null;
// }
//
//
// /* peer item is not reliable for general use
// public PEPeerTransport getTransportFromPeerItem(PeerItem peerItem)
// {
// ArrayList peer_transports =peer_transports_cow;
// for (int i =0; i <peer_transports.size(); i++)
// {
// PEPeerTransport pt =(PEPeerTransport) peer_transports.get(i);
// if (pt.getPeerItemIdentity().equals(peerItem))
// return pt;
// }
// return null;
// }
// */
//
// public PEPeerTransport getTransportFromAddress(String peer)
// {
// final ArrayList peer_transports =peer_transports_cow;
// for (int i =0; i <peer_transports.size(); i++)
// {
// final PEPeerTransport pt =(PEPeerTransport) peer_transports.get(i);
// if (peer.equals(pt.getIp()))
// return pt;
// }
// return null;
// }
//
// // Snubbed peers accounting
// public void incNbPeersSnubbed()
// {
// nbPeersSnubbed++;
// }
//
// public void decNbPeersSnubbed()
// {
// nbPeersSnubbed--;
// }
//
// public void setNbPeersSnubbed(int n)
// {
// nbPeersSnubbed =n;
// }
//
// public int getNbPeersSnubbed()
// {
// return nbPeersSnubbed;
// }
//
// public boolean
// getPreferUDP()
// {
// return( prefer_udp );
// }
//
// public void
// setPreferUDP(
// boolean prefer )
// {
// prefer_udp = prefer;
// }
//
// public boolean
// isPeerSourceEnabled(
// String peer_source )
// {
// return( adapter.isPeerSourceEnabled( peer_source ));
// }
//
// public void
// peerDiscovered(
// PEPeerTransport finder,
// PeerItem pi )
// {
// final ArrayList peer_manager_listeners = peer_manager_listeners_cow;
//
// for( int i=0; i < peer_manager_listeners.size(); i++ ) {
// try{
// ((PEPeerManagerListener)peer_manager_listeners.get(i)).peerDiscovered( this, pi, finder );
//
// }catch( Throwable e ){
//
// Debug.printStackTrace(e);
// }
// }
// }
//
// public void
// generateEvidence(
// IndentWriter writer )
// {
// writer.println( "PeerManager: seeding=" + seeding_mode );
//
// writer.println(
// " udp_fb=" + pending_nat_traversals.size() +
// ",udp_tc=" + udp_traversal_count +
// ",pd=[" + peer_database.getString() + "]");
//
// String pending_udp = "";
//
// try{
// peer_transports_mon.enter();
//
// Iterator it = pending_nat_traversals.values().iterator();
//
// while( it.hasNext()){
//
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// pending_udp += (pending_udp.length()==0?"":",") + peer.getPeerItemIdentity().getAddressString() + ":" + peer.getPeerItemIdentity().getUDPPort();
// }
// }finally{
//
// peer_transports_mon.exit();
// }
//
// if ( pending_udp.length() > 0 ){
//
// writer.println( " pending_udp=" + pending_udp );
// }
//
// List traversals = PeerNATTraverser.getSingleton().getTraversals( this );
//
// String active_udp = "";
//
// Iterator it = traversals.iterator();
//
// while( it.hasNext()){
//
// InetSocketAddress ad = (InetSocketAddress)it.next();
//
// active_udp += (active_udp.length()==0?"":",") + ad.getAddress().getHostAddress() + ":" + ad.getPort();
// }
//
// if ( active_udp.length() > 0 ){
//
// writer.println( " active_udp=" + active_udp );
// }
//
// if ( !seeding_mode ){
//
// writer.println( " Active Pieces" );
//
// int num_active = 0;
//
// try{
// writer.indent();
//
// String str = "";
// int num = 0;
//
// for (int i=0;i<pePieces.length;i++){
//
// PEPiece piece = pePieces[i];
//
// if ( piece != null ){
//
// num_active++;
//
// str += (str.length()==0?"":",") + "#" + i + " " + dm_pieces[i].getString() + ": " + piece.getString();
//
// num++;
//
// if ( num == 20 ){
//
// writer.println( str );
// str = "";
// num = 0;
// }
// }
// }
//
// if ( num > 0 ){
// writer.println(str);
// }
//
// }finally{
//
// writer.exdent();
// }
//
// if ( num_active == 0 ){
//
// writer.println( " Inactive Pieces (excluding done/skipped)" );
//
// try{
// writer.indent();
//
// String str = "";
// int num = 0;
//
// for (int i=0;i<dm_pieces.length;i++){
//
// DiskManagerPiece dm_piece = dm_pieces[i];
//
// if ( dm_piece.isInteresting()){
//
// str += (str.length()==0?"":",") + "#" + i + " " + dm_pieces[i].getString();
//
// num++;
//
// if ( num == 20 ){
//
// writer.println( str );
// str = "";
// num = 0;
// }
// }
// }
//
// if ( num > 0 ){
//
// writer.println(str);
// }
//
// }finally{
//
// writer.exdent();
// }
// }
//
// piecePicker.generateEvidence( writer );
// }
//
// try{
// peer_transports_mon.enter();
//
// writer.println( "Peers: total = " + peer_transports_cow.size());
//
// writer.indent();
//
// try{
// writer.indent();
//
// it = peer_transports_cow.iterator();
//
// while( it.hasNext()){
//
// PEPeerTransport peer = (PEPeerTransport)it.next();
//
// peer.generateEvidence( writer );
// }
// }finally{
//
// writer.exdent();
// }
// }finally{
//
// peer_transports_mon.exit();
//
// writer.exdent();
// }
//
// disk_mgr.generateEvidence( writer );
// }
//}