⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trtrackerbtannouncerimpl.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
 * File    : TRTrackerBTAnnouncerImpl.java
 * Created : 5 Oct. 2003
 * By      : Parg 
 * 
 * Azureus - a Java Bittorrent client
 *
 * 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.
 *
 * 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 ( see the LICENSE file ).
 *
 * 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
 */

package org.gudy.azureus2.core3.tracker.client.impl.bt;

import java.io.*;
import java.net.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.net.ssl.*;

import java.util.zip.*;

import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.config.*;
import org.gudy.azureus2.core3.torrent.*;
import org.gudy.azureus2.core3.security.*;
import org.gudy.azureus2.core3.tracker.client.*;
import org.gudy.azureus2.core3.tracker.client.impl.*;
import org.gudy.azureus2.core3.util.*;
import org.gudy.azureus2.core3.internat.*;
//import org.gudy.azureus2.core3.peer.util.*;
import org.gudy.azureus2.core3.peer.*;

import org.gudy.azureus2.core3.tracker.protocol.*;
import org.gudy.azureus2.core3.tracker.protocol.udp.*;
import org.gudy.azureus2.core3.tracker.util.TRTrackerUtils;

import org.gudy.azureus2.plugins.clientid.*;
import org.gudy.azureus2.plugins.download.*;
import org.gudy.azureus2.pluginsimpl.local.clientid.ClientIDManagerImpl;

import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition;
import com.aelitis.azureus.core.dht.netcoords.DHTNetworkPositionManager;
import com.aelitis.azureus.core.networkmanager.impl.udp.UDPNetworkManager;
import com.aelitis.net.udp.uc.PRUDPPacket;
import com.aelitis.net.udp.uc.PRUDPPacketHandler;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerException;
import com.aelitis.net.udp.uc.PRUDPPacketHandlerFactory;
import com.aelitis.net.udp.uc.PRUDPPacketRequest;


/**
 * 
 * This class handles communication with the tracker
 * 
 * @author Olivier
 *
 */
public class 
TRTrackerBTAnnouncerImpl
	extends TRTrackerAnnouncerImpl
{
	
		
	private static final int OVERRIDE_PERIOD			= 10*1000;
	 
	protected static Timer	tracker_timer = new Timer( "Tracker Timer", 32);
	
	public static String 	UDP_REALM = "UDP Tracker";
	
    static{
	  	PRUDPTrackerCodecs.registerCodecs();
	}
	
	private static AEMonitor 	class_mon 			= new AEMonitor( "TRTrackerBTAnnouncer:class" );
	private static Map			tracker_report_map	= new HashMap();
	
    
	private TOTorrent				torrent;
	
	private TimerEvent				current_timer_event;
	private TimerEventPerformer		timer_event_action;
	
	protected int				tracker_state 			= TS_INITIALISED;
	private String				tracker_status_str		= "";
	private TRTrackerAnnouncerResponse	last_response			= null;
	private long				last_update_time_secs;
	private long				current_time_to_wait_secs;
	private boolean				manual_control;
  
	private long min_interval = 0;
  
	private int  failure_added_time = 0;
    private long failure_time_last_updated = 0;
	
	private boolean			stopped;
	private boolean			stopped_for_queue;
	private boolean			completed;
	private boolean			complete_reported	= false;
	
	private boolean			update_in_progress	= false;
	
	private long			rd_last_override = 0;
	private int				rd_override_percentage	= 100;

	private long			min_interval_override	= 0;
	
  	private List trackerUrlLists;
     
  	private URL lastUsedUrl;
  	private URL	lastAZTrackerCheckedURL;
    
  	private HashWrapper			torrent_hash;
  	
	private String	last_tracker_message;		// per torrent memory
	
	private String info_hash = "info_hash=";
	private byte[] tracker_peer_id;
	private String tracker_peer_id_str = "&peer_id=";
	
	private byte[] data_peer_id;
	
	private String 					key_id			= "";
	private static final int	   	key_id_length	= 8;
	private int						key_udp;
	
  
	private String tracker_id = "";
  
  
 
	private String 		ip_override;
	private String[]	peer_networks;
		
	private TRTrackerAnnouncerDataProvider 	announce_data_provider;
	
	protected AEMonitor this_mon 	= new AEMonitor( "TRTrackerBTAnnouncer" );

	private boolean	az_tracker;
	private boolean	destroyed;
		


	static final String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

	public static String
	createKeyID()
	{
		String	key_id = "";
		
		for (int i = 0; i < key_id_length; i++) {
			int pos = (int) ( Math.random() * chars.length());
		    key_id +=  chars.charAt(pos);
		}
		
		return( key_id );
	}
	
  public 
  TRTrackerBTAnnouncerImpl(
   	TOTorrent		_torrent,
	String[]		_peer_networks,
	boolean			_manual ) 
  	
  	throws TRTrackerAnnouncerException
  {
  	torrent			= _torrent;
  	peer_networks	= _peer_networks;
  	manual_control	= _manual;
  	
		//Get the Tracker url
		
	constructTrackerUrlLists( true );
       
		//Create our unique peerId
	
	try{
	    tracker_peer_id = ClientIDManagerImpl.getSingleton().generatePeerID( torrent, true );
	
	    if ( COConfigurationManager.getBooleanParameter("Tracker Separate Peer IDs", false)){
	    	
	    	data_peer_id = ClientIDManagerImpl.getSingleton().generatePeerID( torrent, false );
	    	
	    }else{
	    	
	    	data_peer_id	= tracker_peer_id;
	    }
	}catch( ClientIDException e ){

		 throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: Peer ID generation fails", e ));
	}

    key_id	= createKeyID();
    
	key_udp	= (int)(Math.random() *  0xFFFFFFFFL );
	
	try {
	
		torrent_hash = _torrent.getHashWrapper();
				
		this.info_hash += URLEncoder.encode(new String(torrent_hash.getBytes(), Constants.BYTE_ENCODING), Constants.BYTE_ENCODING).replaceAll("\\+", "%20");
	  
		this.tracker_peer_id_str += URLEncoder.encode(new String(tracker_peer_id, Constants.BYTE_ENCODING), Constants.BYTE_ENCODING).replaceAll("\\+", "%20");
	  
	}catch (UnsupportedEncodingException e){

		Logger.log(new LogEvent(torrent, LOGID, "URL encode fails", e));
	  
	  throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: URL encode fails"));
	  
	}catch( TOTorrentException e ){
	
		Logger.log(new LogEvent(torrent, LOGID, "Torrent hash retrieval fails", e));
		
		throw( new TRTrackerAnnouncerException( "TRTrackerAnnouncer: URL encode fails"));	
	}
	   
	timer_event_action =  
		new TimerEventPerformer()
		{
			public void
			perform(
				TimerEvent	this_event )
			{
				if ( manual_control ){
					
					requestUpdateSupport();
					
					return;
				}
				
				long	secs_to_wait = getErrorRetryInterval();
							
				try{
															
					secs_to_wait = requestUpdateSupport();

					if (Logger.isEnabled())
						Logger.log(new LogEvent(torrent, LOGID,
								"Next tracker announce (unadjusted) will be in " + secs_to_wait
										+ "s"));
								
				}finally{
						
					current_time_to_wait_secs	= secs_to_wait;
							
					if ( tracker_state == TS_STOPPED ){
						
						// System.out.println( "\tperform: stopped so no more events");
						
					}else{
						
					
						try{
							this_mon.enter();
						
								// it is possible that the current event was being processed
								// when another thread cancelled it and created a further timer
								// event. if this is the case we don't want to go ahead and
								// create another timer as one already exists 
								
							if ( this_event.isCancelled()){
								
								// System.out.println( "\tperform: cancelled so no new event");
								
							}else{
								
								
								secs_to_wait = getAdjustedSecsToWait();

								if (Logger.isEnabled())
									Logger.log(new LogEvent(torrent, LOGID,
											"Next tracker announce (adjusted) will be in "
													+ secs_to_wait + "s"));
								
								long target_time = SystemTime.getCurrentTime() + (secs_to_wait*1000);
								
								if ( current_timer_event != null && !current_timer_event.isCancelled()){
									
									if ( 	current_timer_event != this_event &&
											current_timer_event.getWhen() < target_time ){
									
											// existing event is earlier then current target, use it
												
										return;
									}
									
									current_timer_event.cancel();
								}
								
								if ( !destroyed ){
									
									current_timer_event = 
										tracker_timer.addEvent( target_time, this );
								}
							}
						}finally{
							
							this_mon.exit();
						}
					}
				}
			}
		};
    
		if (Logger.isEnabled())
			Logger.log(new LogEvent(torrent, LOGID,
					"Tracker Announcer Created using url : " + trackerURLListToString()));
  }
  	
	protected long
	getAdjustedSecsToWait()
	{

	  long		secs_to_wait = current_time_to_wait_secs;
													
	  if( last_response != null && last_response.getStatus() != TRTrackerAnnouncerResponse.ST_ONLINE ) {
      
	  	if( last_response.getStatus() == TRTrackerAnnouncerResponse.ST_REPORTED_ERROR ) {
	  		
	  		//the tracker has explicitly reported an error (torrent is unauthorized for example),
	  		//so there's no need to keep trying to re-announce as if it were actually offline

	  		//there's no "min interval" returned, so start the re-announce backoff timings at 15min
	  		if( failure_added_time < 900 )  failure_added_time = 900;
  			secs_to_wait = getErrorRetryInterval();
  			
    		if (Logger.isEnabled()) {
					Logger.log(new LogEvent(torrent, LOGID,
							"MIN INTERVAL CALC: tracker reported error, " + 
							"adjusting to error retry interval"));
    		}
	  	}
	  	else {	//tracker is OFFLINE
	  		secs_to_wait = getErrorRetryInterval();
    		if (Logger.isEnabled()) {
					Logger.log(new LogEvent(torrent, LOGID,
							"MIN INTERVAL CALC: tracker seems to be offline, " + 
							"adjusting to error retry interval"));
    		}
	  	}
							
	  }
    else{
        
      if( rd_override_percentage == 0 ) {
				if (Logger.isEnabled())
					Logger.log(new LogEvent(torrent, LOGID,
							"MIN INTERVAL CALC: override, perc = 0"));
      	return REFRESH_MINIMUM_SECS;
      }

      if (rd_override_percentage != 100) {
      	secs_to_wait = (secs_to_wait * rd_override_percentage) /100;
    		if (Logger.isEnabled()) {
					Logger.log(new LogEvent(torrent, LOGID,
							"MIN INTERVAL CALC: override, perc = " + rd_override_percentage));
    		}
      }
									
      if ( secs_to_wait < REFRESH_MINIMUM_SECS ){
	  			
        secs_to_wait = REFRESH_MINIMUM_SECS;
      }
      
      //use 'min interval' for calculation
      if( min_interval != 0 && secs_to_wait < min_interval ) {
        float percentage = (float)min_interval / current_time_to_wait_secs;  //percentage of original interval
        
        //long orig_override = secs_to_wait;
        
        int added_secs = (int)((min_interval - secs_to_wait) * percentage);  //increase by x percentage of difference
        secs_to_wait += added_secs;
        
    		if (Logger.isEnabled())
					Logger.log(new LogEvent(torrent, LOGID,
							"MIN INTERVAL CALC: min_interval=" + min_interval + ", interval="
									+ current_time_to_wait_secs + ", orig=" +  current_time_to_wait_secs
									+ ", new=" + secs_to_wait + ", added=" + added_secs
									+ ", perc=" + percentage));
      }
      
    }
  		
	  return( secs_to_wait );
	}
  
	
	public int
  	getStatus()
  	{
  		return( tracker_state );
  	}
	
  	public String
  	getStatusString()
  	{
  		return( tracker_status_str );
  	}
  	
	public void
	setRefreshDelayOverrides(
		int		percentage )
	{
		if ( percentage > 100 ){
			
			percentage = 100;
			
		}else if ( percentage < 0 ){
			
			percentage	= 0;
		}
		
		long	now = SystemTime.getCurrentTime();
		//only start overriding once the tracker announce update has been called
		boolean override_allowed = rd_last_override > 0 && now - rd_last_override > OVERRIDE_PERIOD;
    
		if( now < rd_last_override )  override_allowed = true;  //time went backwards
    
		if ( override_allowed && rd_override_percentage != percentage ){
		
			try{
				this_mon.enter();

				rd_last_override	= now;
				
				rd_override_percentage	= percentage;
				
				if ( current_timer_event != null && !current_timer_event.isCancelled()){
					
					long	start 	= current_timer_event.getCreatedTime();
					long	expiry	= current_timer_event.getWhen();
					
					long	secs_to_wait = getAdjustedSecsToWait();
								
					long target_time = start + (secs_to_wait*1000);

					if ( target_time != expiry ){
						
						current_timer_event.cancel();
						
						if ( !destroyed ){ 
							
							if (Logger.isEnabled())
								Logger.log(new LogEvent(torrent, LOGID,
										"Changed next tracker announce to " + secs_to_wait
												+ "s via " + Debug.getStackTrace(true, false, 0, 3)));
							
							current_timer_event = 
								tracker_timer.addEvent( 
									start,
									target_time,
									timer_event_action );	
						}
					}			
				}
			}finally{
				
				this_mon.exit();
			}
		}
	}
	
	public int
	getTimeUntilNextUpdate()
	{
		try{
			this_mon.enter();
		
			if ( current_timer_event == null ){
				
				return( getErrorRetryInterval() );
			}
					
			int rem = (int)((current_timer_event.getWhen() - SystemTime.getCurrentTime())/1000);
					
			return( rem );
			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -