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

📄 trtrackerclientclassicimpl.java

📁 Azureus is a powerful, full-featured, cross-platform java BitTorrent client
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
				                
				                if( peer_port < 0 || peer_port > 65535 ) {
				                  LGLogger.log( LGLogger.ERROR, "Invalid peer port given: " +ip+ ": " +peer_port );
				                  continue;
				                }
								
								byte[] peer_peer_id;
								
								// extension - if peer id is missing then the tracker isn't sending
								// peer ids to save on bandwidth. However, we need something "unique" to 
								// work on internally so make an ID up from the ip and port
								
								if ( s_peerid == null ){
	                
									// Debug.out(ip + ": tracker did not give peerID in reply");

									peer_peer_id = getAnonymousPeerId( ip, peer_port );
									
									// System.out.println("generated peer id" + new String(peerId) + "/" + ByteFormatter.nicePrint( peerId, true ));
								}else{
								
									peer_peer_id = (byte[])s_peerid ; 
								}
								
								if ( PeerUtils.ignorePeerPort( peer_port )){
								
			 			    		LGLogger.log(
						    				componentID, evtFullTrace, LGLogger.INFORMATION, 
						    				"Ignoring " + ip + ":" + peer_port + " as peer port is in ignore list" );

								}else{
									
									valid_meta_peers.add(new TRTrackerResponsePeerImpl( peer_peer_id, ip, peer_port ));
								}
							} 
						}
				    }else{
				    	
				    		// byte[] for compact returns
				    	
				    
				    	byte[]	meta_peers = (byte[])meta_peers_peek;
				    	
				    	for (int i=0;i<meta_peers.length;i+=6){
				    		
				    		int	ip1 = 0xFF & meta_peers[i];
				    		int	ip2 = 0xFF & meta_peers[i+1];
				    		int	ip3 = 0xFF & meta_peers[i+2];
				    		int	ip4 = 0xFF & meta_peers[i+3];
				    		int	po1 = 0xFF & meta_peers[i+4];
				    		int	po2 = 0xFF & meta_peers[i+5];
				    		
				    		String	ip 		= "" + ip1 + "." + ip2 + "." + ip3 + "." + ip4;
				    		int		peer_port 	= po1*256+po2;
				    		
			                if( peer_port < 0 || peer_port > 65535 ) {
			                  LGLogger.log( LGLogger.ERROR, "Invalid compact peer port given: " +ip+ ": " +peer_port );
			                  continue;
			                }
                
				    		byte[]	peer_peer_id = getAnonymousPeerId( ip, peer_port );
							
				    		LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
				    				"COMPACT PEER: ip=" +ip+ " port=" +peer_port);
							
                			if ( PeerUtils.ignorePeerPort( peer_port )){
					
        			    		LGLogger.log(
        			    				componentID, evtFullTrace, LGLogger.INFORMATION, 
    				    				"    Ignoring as peer port is in ignore list" );
    	
                			}else{
                				valid_meta_peers.add(new TRTrackerResponsePeerImpl( peer_peer_id, ip, peer_port ));
                			}
				    	}
				    }
				    
					TRTrackerResponsePeer[] peers=new TRTrackerResponsePeer[valid_meta_peers.size()];
					
					valid_meta_peers.toArray(peers);
					
					addToTrackerCache( peers);
					
					TRTrackerResponseImpl resp = new TRTrackerResponseImpl( TRTrackerResponse.ST_ONLINE, time_to_wait, peers );
          
						//reset failure retry interval on successful connect
					
					failure_added_time = 0;
					
					Map extensions = (Map)metaData.get( "extensions" );
					
					resp.setExtensions(extensions);
					
					if ( extensions != null ){
						
						if ( complete_l == null) {
							complete_l = (Long)extensions.get("complete");
						}
						
						if ( incomplete_l == null) {
							incomplete_l = (Long)extensions.get("incomplete");
						}
					
						LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
			                           "ANNOUNCE SCRAPE2: seeds=" +complete_l+ " peers=" +incomplete_l);
			            
					}

		          if (complete_l != null || incomplete_l != null) {
		          	
		          	int	complete = complete_l==null?0:complete_l.intValue();
		          	
		          	int incomplete = incomplete_l==null?0:incomplete_l.intValue();
		          	
		            TRTrackerScraper scraper = TRTrackerScraperFactory.getSingleton();
		            
		            if (scraper != null) {
		              TRTrackerScraperResponse scrapeResponse = scraper.scrape(this);
		              if (scrapeResponse != null) {
		                long lNextScrapeTime = scrapeResponse.getNextScrapeStartTime();
		                long now = SystemTime.getCurrentTime();
		                
		                long lNewNextScrapeTime =  now + 10*60*1000;
		                
		                	// make it look as if the scrape has just run. Important
		                	// as seeding rules may make calculations on when the 
		                	// scrape value were set
		                
		                scrapeResponse.setScrapeStartTime( now );
		                
		                if (lNextScrapeTime < lNewNextScrapeTime) {
		                	
		                  scrapeResponse.setNextScrapeStartTime(lNewNextScrapeTime);
		                }
		                
		                scrapeResponse.setSeedsPeers( complete, incomplete );
		              }
		            }
       
		            //resp.setScrapeDetails( lComplete.intValue(), lIncomplete.intValue());
		          }
            
		          return( resp );  

				}catch( IOException e ){
					
						// decode could fail if the tracker's returned, say, an HTTP response
						// indicating server overload
	 				 				
	 				String	trace_data = new String(data);
	 				
	 				LGLogger.log("TRTrackerClient::invalid reply: " + trace_data );
	 				
	 				if ( trace_data.length() > 150 ){
	 					
	 					trace_data = trace_data.substring(0,150) + "...";
	 				}
	 				
	 				failure_reason = "invalid reply: " + trace_data;
	 			}	 				
	 		}catch( Throwable e ){
				
	 			Debug.printStackTrace( e );
				
				failure_reason = "error: " + e.getMessage();
			}
  		}

		return( new TRTrackerResponseImpl( TRTrackerResponse.ST_OFFLINE, getErrorRetryInterval(), failure_reason ));
  	}
  	
	protected void
	informURLChange(
		URL		url,
		boolean	explicit  )
	{
		listeners.dispatch(	LDT_URL_CHANGED,
							new Object[]{url.toString(),new Boolean(explicit)});
	}
	
	protected void
	informURLRefresh()
	{
		listeners.dispatch( LDT_URL_REFRESH, null );		
	}
	
	public TRTrackerResponse
	getLastResponse()
	{
    if( last_response == null ) {
      return new TRTrackerResponseImpl(TRTrackerResponse.ST_OFFLINE, TRTrackerClient.REFRESH_MINIMUM_SECS );
    }
		return( last_response );
	}
	
  	public void
	addListener(
		TRTrackerClientListener	l )
	{
		listeners.addListener( l );
	}
		
	public void
	removeListener(
		TRTrackerClientListener	l )
	{
		listeners.removeListener(l);
	}
	
	public void
	destroy()
	{       
		destroyed	= true;
		
		peer_server.removeListener( this );
    
		COConfigurationManager.removeParameterListener("TCP.Announce.Port",this);
		
		TRTrackerClientFactoryImpl.destroy( this );
		
		try{
			this_mon.enter();
			
			if ( current_timer_event != null ){
				
					// cancel any events that are a way off being triggered. note that
					// we don't want to cancel all events as the "stopped" event that
					// is scheduled on stop of a download may still be lurking
				
				if ( current_timer_event.getWhen() - SystemTime.getCurrentTime() > 10*1000 ){
					
					current_timer_event.cancel();
				}
			}
		}finally{
			
			this_mon.exit();
		}
	}
  
  
  /**
   * Retrieve the retry interval to use on announce errors.
   */
  private int getErrorRetryInterval() {
    
    long currentTime = SystemTime.getCurrentTime() /1000;
        
    
    //use previously calculated interval if it's not time to update
    if ( !SystemTime.isErrorLast1min() &&
        ((currentTime - failure_time_last_updated) < failure_added_time)) {
      return failure_added_time;
    }

    //update previous change time
    failure_time_last_updated = currentTime;
    
    if( failure_added_time == 0 ) { //start
      failure_added_time = 10;
    }
    else if( failure_added_time < 30 ) {
      //three 10-sec retries
      failure_added_time += 10;
    }
    else if( failure_added_time < 60 ) {
      //two 15-sec retries
      failure_added_time += 15;
    }
    else if( failure_added_time < 120 ) {
      //two 30-sec retries
      failure_added_time += 30;
    }
    else if( failure_added_time < 600 ) {
      //eight 60-sec retries
      failure_added_time += 60;
    }
    else {
      //2-3min random retry 
      failure_added_time += 120 + new Random().nextInt( 60 );
    }

    boolean is_seed = (announce_data_provider == null) ? false : announce_data_provider.getRemaining() == 0;
    
    if( is_seed ) failure_added_time = failure_added_time * 2; //no need to retry as often
    
    //make sure we're not waiting longer than 20min
    if( !is_seed && failure_added_time > 1200) {
      failure_added_time = 1200;
    }
    else if ( is_seed && failure_added_time > 3600) { //or 60min if seed
      failure_added_time = 3600;
    }

    return failure_added_time;
  }
  
  	protected byte[]
	getAnonymousPeerId(
		String	my_ip,
		int		my_port )
	{
  		byte[] anon_peer_id = new byte[20];
	
  		// unique initial two bytes to identify this as fake

  		anon_peer_id[0] = (byte)'[';
  		anon_peer_id[1] = (byte)']';

  		try{
	  		byte[]	ip_bytes 	= my_ip.getBytes( Constants.DEFAULT_ENCODING );
	  		int		ip_len		= ip_bytes.length;
	
	  		if ( ip_len > 18 ){
		
	  			ip_len = 18;
	  		}
	
	  		System.arraycopy( ip_bytes, 0, anon_peer_id, 2, ip_len );
									
	  		int	port_copy = my_port;
		
	  		for (int j=2+ip_len;j<20;j++){
			
	  			anon_peer_id[j] = (byte)(port_copy&0xff);
			
	  			port_copy >>= 8;
	  		}
  		}catch( UnsupportedEncodingException e ){
  			
  			Debug.printStackTrace( e );
  		}
  		
  		return( anon_peer_id );
   }
	 	
  		// NOTE: tracker_cache is cleared out in DownloadManager when opening a torrent for the
  		// first time as a DOS prevention measure
  
	public Map
	getTrackerResponseCache()
	{				
		return( exportTrackerCache());
	}
	
	
	public void
	setTrackerResponseCache(
		Map		map )
	{
		int	num = importTrackerCache( map );
		
    LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
                 "TRTrackerClient: imported " + num + " cached peers" );
	}
	
	protected Map
	exportTrackerCache()
	{
		Map	res = new HashMap();
		
		List	peers = new ArrayList();
		
		res.put( "tracker_peers", peers );
		
		try{
			tracker_peer_cache_mon.enter();
			
			Iterator it = tracker_peer_cache.values().iterator();
			
			while( it.hasNext()){
				
				TRTrackerResponsePeer	peer = (TRTrackerResponsePeer)it.next();		

				Map	entry = new HashMap();
				
				entry.put( "ip", peer.getIPAddress().getBytes());
				entry.put( "port", new Long(peer.getPort()));
				
				peers.add( entry );
			}
		
			LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
			             "TRTrackerClient: exported " + tracker_peer_cache.size() + " cached peers" );
		}finally{
			
			tracker_peer_cache_mon.exit();
		}
		
		return( res );
	}
	
	protected int
	importTrackerCache(
		Map		map )
	{
		if ( !COConfigurationManager.getBooleanParameter("File.save.peers.enable")){
			
			return( 0 );
		}
		
		try{
			if ( map == null ){
				
				return( 0 );
			}
			
			List	peers = (List)map.get( "tracker_peers" );
	
			if ( peers == null ){
				
				return( 0 );
			}
			
			try{
				tracker_peer_cache_mon.enter();
				
				for (int i=0;i<peers.size();i++){
					
					Map	peer = (Map)peers.get(i);
					
					String	peer_ip_address = new String((byte[])peer.get("ip"));
					int		peer_port		= ((Long)peer.get("port")).intValue();
					byte[]	peer_peer_id	= getAnonymousPeerId( peer_ip_address, peer_port );
						
					//System.out.println( "recovered " + ip_address + ":" + port );
					
					if ( PeerUtils.ignorePeerPort( peer_port )){
						
   			    		LGLogger.log(
			    				componentID, evtFullTrace, LGLogger.INFORMATION, 
			    				"Ignoring " + peer_ip_address + ":" + peer_port + " as peer port is in ignore list" );

					}else{
						tracker_peer_cache.put( 
							peer_ip_address, 
							new TRTrackerResponsePeerImpl(peer_peer_id, peer_ip_address, peer_port ));
					}
				}
				
				return( tracker_peer_cache.size());
				
			}finally{
				
				tracker_peer_cache_mon.exit();
			}
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
			
			return( tracker_peer_cache.size());
		}
	}
	
	protected void
	addToTrackerCache(
		TRTrackerResponsePeer[]		peers )
	{
		if ( !COConfigurationManager.getBooleanParameter("File.save.peers.enable")){
			
			return;
		}
		
		int	max = COConfigurationManager.getIntParameter( "File.save.peers.max", DEFAULT_PEERS_TO_CACHE );
		
		// System.out.println( "max peers= " + max );
		
		try{
			tracker_peer_cache_mon.enter();
			
			for (int i=0;i<peers.length;i++){
				
				TRTrackerResponsePeer	peer = peers[i];
				
					// remove and reinsert to maintain most recent last
				
				tracker_peer_cache.remove( peer.getIPAddress());
				
				tracker_peer_cache.put( peer.getIPAddress(), peer );
			}
			
			Iterator	it = tracker_peer_cache.keySet().iterator();
			
			if ( max > 0 ){
					
				while ( tracker_peer_cache.size() > max ){
						
					it.next();
					
					it.remove();
				}
			}
		}finally{
			
			tracker_peer_cache_mon.exit();
		}
	}
	
	public static Map
	mergeResponseCache(
		Map		map1,
		Map		map2 )
	{
		if ( map1 == null & map2 == null ){
			return( new HashMap());
		}else if ( map1 == null ){
			return( map2 );
		}else if ( map2 == null ){
			return( map1 );
		}
		
		Map	res = new HashMap();
				
		List	peers = (List)map1.get( "tracker_peers" );
		
		if ( peers == null ){
			
			peers = new ArrayList();
		}
		
		List	p2 = (List)map2.get( "tracker_peers" );
		
		if ( p2 != null ){
			
      LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
			             "TRTrackerClient: merged peer sets: p1 = " + peers.size() + ", p2 = " + p2.size());
		
			for (int i=0;i<p2.size();i++){
				
				peers.add( p2.get( i ));
			}
		}
		
		res.put( "tracker_peers", peers );
		
		return( res );
	}
	
	protected TRTrackerResponsePeer[]
	getPeersFromCache()
	{
			// use double the num_want as no doubt a fair few connections will fail and
			// we want to get a decent reconnect rate
		
		int	num_want = calculateNumWant() * 4;
	
		try{
			tracker_peer_cache_mon.enter();

			if ( tracker_peer_cache.size() <= num_want ){
				
				TRTrackerResponsePeer[]	res = new TRTrackerResponsePeer[tracker_peer_cache.size()];
				
				tracker_peer_cache.values().toArray( res );
				
			    LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
		                   "TRTrackerClient: returned " + res.length + " cached peers" );
			    
				return( res );
			}
			
			TRTrackerResponsePeer[]	res = new TRTrackerResponsePeer[num_want];
			
			Iterator	it = tracker_peer_cache.keySet().iterator();
			
				// take 'em out and put them back in so we cycle through the peers
				// over time
			
			for (int i=0;i<num_want;i++){
				
				String	key = (String)it.next();
				
				res[i] = (TRTrackerResponsePeer)tracker_peer_cache.get(key);
				
				it.remove();
			}
			
			for (int i=0;i<num_want;i++){
				
				tracker_peer_cache.put( res[i].getIPAddress(), res[i] );
			}
			
		    LGLogger.log(componentID, evtFullTrace, LGLogger.INFORMATION, 
	                   "TRTrackerClient: returned " + res.length + " cached peers" );
		    
			return( res );
			
		}finally{
			
			tracker_peer_cache_mon.exit();
		}
	} 
  
  
  
  // ParameterListener Implementation
  public void parameterChanged(String parameterName) {
    if("TCP.Announce.Port".equals(parameterName)) {
      setPort();
    }
  }
}

⌨️ 快捷键说明

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