FileDocCategorySizeDatePackage
TRTrackerServerProcessor.javaAPI DocAzureus 3.0.3.413905Wed Sep 12 23:18:04 BST 2007org.gudy.azureus2.core3.tracker.server.impl

TRTrackerServerProcessor

public abstract class TRTrackerServerProcessor extends ThreadPoolTask
author
parg

Fields Summary
private static final boolean
QUEUE_TEST
private TRTrackerServerImpl
server
Constructors Summary
Methods Summary
protected voidaddScrapeInterval(TRTrackerServerTorrentImpl torrent, java.util.Map root)

		long interval = server.getScrapeRetryInterval( torrent );

		addScrapeInterval( interval, root );
	
protected voidaddScrapeInterval(long interval, java.util.Map root)

		if ( interval > 0 ){
			
			Map	flags = new HashMap();
			
			flags.put("min_request_interval", new Long(interval));
			
			root.put( "flags", flags );
		}
	
protected TRTrackerServerTorrentImplprocessTrackerRequest(TRTrackerServerImpl _server, java.lang.String request, java.util.Map[] root_out, TRTrackerServerPeerImpl[] peer_out, int request_type, byte[][] hashes, java.lang.String link, java.lang.String scrape_flags, HashWrapper peer_id, boolean no_peer_id, byte compact_mode, java.lang.String key, java.lang.String event, boolean stop_to_queue, int port, int udp_port, int http_port, java.lang.String real_ip_address, java.lang.String client_ip_address, long downloaded, long uploaded, long left, int num_want, byte crypto_level, byte az_ver, int up_speed, com.aelitis.azureus.core.dht.netcoords.DHTNetworkPosition network_position)

		server	= _server;
			
		if ( !server.isReady()){
			
			throw( new TRTrackerServerException( "Tracker initialising, please wait" ));
		}
		
		boolean	ip_override = real_ip_address != client_ip_address;
		
		boolean	loopback	= TRTrackerUtils.isLoopback( real_ip_address );
		
		if ( loopback ){
					
				// any override is purely for routing purposes for loopback connections and we don't
				// want to apply the ip-override precedence rules against us 
						
			ip_override	= false;
		}
		
			// translate any 127.0.0.1 local addresses back to the tracker address. Note this
			// fixes up .i2p and onion addresses back to their real values when needed
		
		client_ip_address = TRTrackerUtils.adjustHostFromHosting( client_ip_address );
		
		if ( !TRTrackerServerImpl.getAllNetworksSupported()){
		
			String	network = AENetworkClassifier.categoriseAddress( client_ip_address );
			
			String[]	permitted_networks = TRTrackerServerImpl.getPermittedNetworks();
			
			boolean ok = false;
			
			for (int i=0;i<permitted_networks.length;i++){
				
				if ( network == permitted_networks[i] ){
					
					ok = true;
					
					break;
				}
			}
			
			if ( !ok ){
				
				throw( new TRTrackerServerException( "Network '" + network + "' not supported" ));
			}
		}
				
		TRTrackerServerTorrentImpl	torrent = null;
		
		if ( request_type != TRTrackerServerRequest.RT_FULL_SCRAPE ){
									
			// System.out.println( "TRTrackerServerProcessor::request:" + request_type + ",event:" + event + " - " + client_ip_address + ":" + port );
			
			// System.out.println( "    hash = " + ByteFormatter.nicePrint(hash));
			
			if ( request_type == TRTrackerServerRequest.RT_ANNOUNCE ){
				
				if ( hashes == null || hashes.length == 0 ){
					
					throw( new TRTrackerServerException( "Hash missing from request "));
				}

				if ( hashes.length != 1 ){
					
					throw( new TRTrackerServerException( "Too many hashes for announce"));
				}
				
				byte[]	hash = hashes[0];
				
				torrent = server.getTorrent( hash );
				
				if ( torrent == null ){
					
					if ( !COConfigurationManager.getBooleanParameter( "Tracker Public Enable")){
						
						throw( new TRTrackerServerException( "Torrent unauthorised" ));
						
					}else{
						
						try{
							
							torrent = (TRTrackerServerTorrentImpl)server.permit( real_ip_address, hash, false );
													
						}catch( Throwable e ){
							
							throw( new TRTrackerServerException( "Torrent unauthorised", e ));								
						}
					}
				}
				
				if ( peer_id == null ){
					
					throw( new TRTrackerServerException( "peer_id missing from request"));
				}
				
				boolean	queue_it = stop_to_queue && ( QUEUE_TEST || !( loopback || ip_override ));

				long	interval;
				long	min_interval;
				
				if ( queue_it ){
					
						// when queued we use the scrape timeouts as it is scrape operations that
						// will keep the entry alive from this point on
					
					interval 		= server.getScrapeRetryInterval( torrent );
					min_interval	= server.getMinScrapeRetryInterval();
					
				}else{
					
					interval 		= server.getAnnounceRetryInterval( torrent );
					min_interval 	= server.getMinAnnounceRetryInterval();
				}
				
				TRTrackerServerPeerImpl peer = 
					torrent.peerContact( 	
						request,
						event, 
						peer_id, port, udp_port, http_port, crypto_level, az_ver,
						real_ip_address, client_ip_address, ip_override, loopback, key,
						uploaded, downloaded, left,
						interval,
						up_speed, network_position );
				
				if ( queue_it ){
					
					torrent.peerQueued( client_ip_address, port, udp_port, http_port, crypto_level, az_ver, interval, left==0 );
				}
				
				HashMap	pre_map = new HashMap();
				
				TRTrackerServerPeer	pre_process_peer = peer;
				
				if ( pre_process_peer == null ){
					
						// can be null for stop events received without a previous start
					
					pre_process_peer = new lightweightPeer(client_ip_address,port,peer_id);
				}
				
				server.preProcess( pre_process_peer, torrent, request_type, request, pre_map );
				
					// set num_want to 0 for stopped events as no point in returning peers
				
				boolean	stopped 	= event != null && event.equalsIgnoreCase("stopped");
				
				root_out[0] = torrent.exportAnnounceToMap( client_ip_address, pre_map, peer, left > 0, stopped?0:num_want, interval, min_interval, no_peer_id, compact_mode, crypto_level, network_position );
				
				peer_out[0]	= peer;	
				
			}else if ( request_type == TRTrackerServerRequest.RT_QUERY ){
				
				if ( link == null ){
					
					if ( hashes == null || hashes.length == 0 ){
						
						throw( new TRTrackerServerException( "Hash missing from request "));
					}
					
					if ( hashes.length != 1 ){
						
						throw( new TRTrackerServerException( "Too many hashes for query"));
					}
				
					byte[]	hash = hashes[0];
				
					torrent = server.getTorrent( hash );
					
				}else{
					
					torrent = server.getTorrent( link );
				}
				
				if ( torrent == null ){
					
					throw( new TRTrackerServerException( "Torrent unauthorised" ));
				}
				
				long	interval = server.getAnnounceRetryInterval( torrent );

				root_out[0] = torrent.exportAnnounceToMap( client_ip_address, new HashMap(), null, true, num_want, interval, server.getMinAnnounceRetryInterval(), true, compact_mode, crypto_level, network_position );

			}else{
				
				if ( hashes == null || hashes.length == 0 ){
					
					throw( new TRTrackerServerException( "Hash missing from request "));
				}

				boolean	local_scrape = client_ip_address.equals( "127.0.0.1" );
				
				long	max_interval	= server.getMinScrapeRetryInterval();
				
				Map	root = new HashMap();
				
				root_out[0] = root;
				
				Map	files = new ByteEncodedKeyHashMap();
				
				root.put( "files", files );
				
				char[]	scrape_chars = scrape_flags==null?null:scrape_flags.toCharArray();
				
				if ( scrape_chars != null && scrape_chars.length != hashes.length ){
					
					scrape_chars	= null;
				}
				
				for (int i=0;i<hashes.length;i++){
					
					byte[]	hash = hashes[i];
					
					String	str_hash;
					
					try{
						str_hash = new String( hash, Constants.BYTE_ENCODING );

							// skip duplicates
						
						if ( i > 0 && files.get( str_hash ) != null ){
							
							continue;
						}
						
					}catch( UnsupportedEncodingException e ){
						
						continue;
					}
					
					torrent = server.getTorrent( hash );
					
					if ( torrent == null ){
						
						if ( !COConfigurationManager.getBooleanParameter( "Tracker Public Enable")){
							
							continue;
							
						}else{
							
							try{							
								torrent = (TRTrackerServerTorrentImpl)server.permit( real_ip_address, hash, false );
									
							}catch( Throwable e ){
								
								continue;							
							}
						}
					}
					
					long	interval = server.getScrapeRetryInterval( torrent );				
					
					if ( interval > max_interval ){
						
						max_interval	= interval;
					}

					if ( scrape_chars != null && ( QUEUE_TEST || !( loopback || ip_override ))){ 
						
							// note, 'Q' is complete+queued so we set seed true below
						
						if ( scrape_chars[i] == 'Q" ){
							
							torrent.peerQueued(  client_ip_address, port, udp_port, http_port, crypto_level, az_ver, (int)interval, true );
						}
					}
					
					if ( torrent.getRedirects() != null ){
						
						if ( hashes.length > 1 ){
							
								// just drop this from the set. this will cause the client to revert
								// to single-hash scrapes and subsequently pick up the redirect
							
							continue;							
						}
					}
					
					server.preProcess( new lightweightPeer(client_ip_address,port,peer_id), torrent, request_type, request, null );

					// we don't cache local scrapes as if we do this causes the hosting of
					// torrents to retrieve old values initially. Not a fatal error but not
					// the best behaviour as the (local) seed isn't initially visible.
				
					Map	hash_entry = torrent.exportScrapeToMap( request, client_ip_address, !local_scrape );
										
						// System.out.println( "tracker - encoding: " + ByteFormatter.nicePrint(torrent_hash) + " -> " + ByteFormatter.nicePrint( str_hash.getBytes( Constants.BYTE_ENCODING )));
					
					files.put( str_hash, hash_entry );
				}
				
				if ( hashes.length > 1 ){
					
					torrent	= null;	// no specific torrent
				}
				
				// System.out.println( "scrape: hashes = " + hashes.length + ", files = " + files.size() + ", tim = " + max_interval );
				
				addScrapeInterval( max_interval, root );
			}
		}else{
			
			
			if ( !TRTrackerServerImpl.isFullScrapeEnabled()){
				
				throw( new TRTrackerServerException( "Full scrape disabled" ));
			}
			
			Map	files = new ByteEncodedKeyHashMap();
				
			TRTrackerServerTorrentImpl[] torrents = server.getTorrents();
			
			for (int i=0;i<torrents.length;i++){
				
				TRTrackerServerTorrentImpl	this_torrent = torrents[i];
					
				if ( this_torrent.getRedirects() != null ){
					
						// not visible to a full-scrape
					
					continue;
				}
				
				server.preProcess( new lightweightPeer(client_ip_address,port,peer_id), this_torrent, request_type, request, null );

				byte[]	torrent_hash = this_torrent.getHash().getHash();
				
				try{
					String	str_hash = new String( torrent_hash,Constants.BYTE_ENCODING );
					
					// System.out.println( "tracker - encoding: " + ByteFormatter.nicePrint(torrent_hash) + " -> " + ByteFormatter.nicePrint( str_hash.getBytes( Constants.BYTE_ENCODING )));
					
					Map	hash_entry = this_torrent.exportScrapeToMap( request, client_ip_address, true );
					
					files.put( str_hash, hash_entry );
					
				}catch( UnsupportedEncodingException e ){
			
					throw( new TRTrackerServerException( "Encoding error", e ));

				}
			}
			
			Map	root = new HashMap();
			
			root_out[0] = root;
			
			addScrapeInterval( null, root );
			
			root.put( "files", files );
		}
		
		return( torrent );