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

📄 azinstancemanagerimpl.java

📁 这是一个基于java编写的torrent的P2P源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Created on 20-Dec-2005
 * Created by Paul Gardner
 * Copyright (C) 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 com.aelitis.azureus.core.instancemanager.impl;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.logging.LogEvent;
import org.gudy.azureus2.core3.logging.LogIDs;
import org.gudy.azureus2.core3.logging.Logger;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AESemaphore;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.BDecoder;
import org.gudy.azureus2.core3.util.BEncoder;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.SHA1Simple;
import org.gudy.azureus2.core3.util.SimpleTimer;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.core3.util.TimerEvent;
import org.gudy.azureus2.core3.util.TimerEventPerformer;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;

import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.AzureusCoreLifecycleAdapter;
import com.aelitis.azureus.core.instancemanager.AZInstance;
import com.aelitis.azureus.core.instancemanager.AZInstanceManager;
import com.aelitis.azureus.core.instancemanager.AZInstanceManagerListener;
import com.aelitis.azureus.core.instancemanager.AZInstanceTracked;
import com.aelitis.azureus.core.util.NetUtils;
import com.aelitis.net.udp.mc.MCGroup;
import com.aelitis.net.udp.mc.MCGroupAdapter;
import com.aelitis.net.udp.mc.MCGroupFactory;

public class 
AZInstanceManagerImpl 
	implements AZInstanceManager, MCGroupAdapter
{
	private static final boolean DISABLE_LAN_LOCAL_STUFF	= false;
	
	static{
		if ( DISABLE_LAN_LOCAL_STUFF ){
			System.out.println( "**** LAN LOCAL STUFF DISABLED ****" );
		}
	}
	
	private static final LogIDs LOGID = LogIDs.NET;
	
	private String				MC_GROUP_ADDRESS 	= "239.255.067.250";	// 239.255.000.000-239.255.255.255 
	private int					MC_GROUP_PORT		= 16680;				//
	private int					MC_CONTROL_PORT		= 0;

	private static final int	MT_VERSION		= 1;
	
	private static final int	MT_ALIVE		= 1;
	private static final int	MT_BYE			= 2;
	private static final int	MT_REQUEST		= 3;
	private static final int	MT_REPLY		= 4;
	
	private static final int	MT_REQUEST_SEARCH	= 1;
	private static final int	MT_REQUEST_TRACK	= 2;
	
	private static final long	ALIVE_PERIOD	= 30*60*1000;
	
	private static AZInstanceManagerImpl	singleton;
	
	private List	listeners	= new ArrayList();
	
	private static AEMonitor	class_mon = new AEMonitor( "AZInstanceManager:class" );
	
	private static String	socks_proxy	= null;
	
	static{
		COConfigurationManager.addAndFireParameterListeners(
			new String[]{ "Proxy.Data.Enable", "Proxy.Host", "Proxy.Data.Same", "Proxy.Data.Host" },
			new ParameterListener()
			{
				public void 
				parameterChanged(
					String parameterName )
				{
					if ( !COConfigurationManager.getBooleanParameter("Proxy.Data.Enable")){
						
						socks_proxy = null;
						
						return;
					}
					
					if ( COConfigurationManager.getBooleanParameter("Proxy.Data.Same")){
						
						socks_proxy = COConfigurationManager.getStringParameter( "Proxy.Host" );
						
					}else{
						
						socks_proxy = COConfigurationManager.getStringParameter( "Proxy.Data.Host" );

					}
					
					if ( socks_proxy != null ){
						
						socks_proxy	= socks_proxy.trim();
					}
				}
			});
	}
	
	public static AZInstanceManager
	getSingleton(
		AzureusCore	core )
	{
		try{
			class_mon.enter();
			
			if ( singleton == null ){
				
				singleton = new AZInstanceManagerImpl( core );
			}
		}finally{
			
			class_mon.exit();
		}
		
		return( singleton );
	}
	
	private AzureusCore	core;
	private MCGroup	 	mc_group;
	private long		search_id_next;
	private List		requests = new ArrayList();
	
	private AZMyInstanceImpl		my_instance;
	private Map						other_instances	= new HashMap();
	
	private volatile Map			tcp_lan_to_ext	= new HashMap();
	private volatile Map			udp_lan_to_ext	= new HashMap();
	private volatile Map			udp2_lan_to_ext	= new HashMap();
	private volatile Map			tcp_ext_to_lan	= new HashMap();
	private volatile Map			udp_ext_to_lan	= new HashMap();
	private volatile Map			udp2_ext_to_lan	= new HashMap();
	
	private volatile Set			lan_addresses	= new HashSet();
	private volatile Set			ext_addresses	= new HashSet();
	
	private volatile List			lan_subnets		= new ArrayList();
	private volatile List			explicit_peers 	= new ArrayList();
	
	private volatile boolean		include_well_known_lans	= true;
	
	private AESemaphore	initial_search_sem	= new AESemaphore( "AZInstanceManager:initialSearch" );
	
	private AEMonitor	this_mon = new AEMonitor( "AZInstanceManager" );

	private boolean		closing;
	
	protected
	AZInstanceManagerImpl(
		AzureusCore	_core )
	{
		core			= _core;
		
		my_instance	= new AZMyInstanceImpl( core, this );
		
		new AZPortClashHandler( this );
	}
	
	public void
	initialize()
	{		
		try{
			mc_group = 
				MCGroupFactory.getSingleton(
					this,
					MC_GROUP_ADDRESS,
					MC_GROUP_PORT,
					MC_CONTROL_PORT,
					null );
					
			core.addLifecycleListener(
				new AzureusCoreLifecycleAdapter()
				{
					public void
					stopping(
						AzureusCore		core )
					{
						closing	= true;
						
						sendByeBye();
					}
				});
			
			SimpleTimer.addPeriodicEvent(
				"InstManager:timeouts",
				ALIVE_PERIOD,
				new TimerEventPerformer()
				{
					public void
					perform(
						TimerEvent	event )
					{
						checkTimeouts();
													
						sendAlive();				
					}
				});
		
		}catch( Throwable e ){
			
			initial_search_sem.releaseForever();
			
			Debug.printStackTrace(e);
		}
		
		new AEThread( "AZInstanceManager:initialSearch", true )
		{
			public void
			runSupport()
			{
				try{
					search();
					
						// pick up our own details as soon as we can
					
					addAddresses( my_instance );
					
				}finally{
					
					initial_search_sem.releaseForever();
				}
			}
		}.start();
	}
	
	public void
	trace(
		String	str )
	{
		if ( Logger.isEnabled()){
				
			Logger.log(new LogEvent( LOGID, str )); 
		}
	}
	
	public void
	log(
		Throwable e )
	{
		Debug.printStackTrace(e);
	}
	
	public boolean
	isInitialized()
	{
		return( initial_search_sem.isReleasedForever());
	}
	
	protected boolean
	isClosing()
	{
		return( closing );
	}
	
	protected void
	sendAlive()
	{
		sendMessage( MT_ALIVE );
	}
	
	protected void
	sendAlive(
		InetSocketAddress	target )
	{
		sendMessage( MT_ALIVE, target );
	}
	
	protected void
	sendByeBye()
	{
		sendMessage( MT_BYE );
	}
	
	protected void
	sendByeBye(
		InetSocketAddress	target )
	{
		sendMessage( MT_BYE, target );
	}
	
	protected void
	sendMessage(
		int		type )
	{
		sendMessage( type, (Map)null );
	}
	
	protected void
	sendMessage(
		int					type,
		InetSocketAddress	target )
	{
		sendMessage( type, null, target );
	}
	
	protected void
	sendMessage(
		int		type,
		Map		body )
	{
		sendMessage( type, body, null );
	}
	
	protected void
	sendMessage(
		int					type,
		Map					body,
		InetSocketAddress	member )
	{
		Map	map = new HashMap();
		
		map.put( "ver", new Long(MT_VERSION));
		map.put( "type", new Long(type));
		
		Map	originator = new HashMap();
		
		map.put( "orig", originator );
		
		my_instance.encode( originator );
		
		if ( body != null ){
			
			map.put( "body", body );
		}
				
		try{
			
			if ( member == null ){
				
				byte[]	data = BEncoder.encode( map );

				mc_group.sendToGroup( data );
				
				if ( explicit_peers.size() > 0 ){
					
					map.put( "explicit", new Long(1));
				
					byte[]	explicit_data = BEncoder.encode( map );
					
					Iterator	it = explicit_peers.iterator();
				
					while( it.hasNext()){
					
						mc_group.sendToMember((InetSocketAddress)it.next(), explicit_data );
					}
				}
			}else{
				
				if ( explicit_peers.contains( member )){
					
					map.put( "explicit", new Long(1));
				}
				
				byte[]	explicit_data = BEncoder.encode( map );

				mc_group.sendToMember( member, explicit_data );
			}
		}catch( Throwable e ){
			
		}
	}

	public void
	received(
		NetworkInterface	network_interface,
		InetAddress			local_address,
		InetSocketAddress	originator,
		byte[]				data,
		int					length )
	{
		try{
			Map	map = BDecoder.decode(new BufferedInputStream(new ByteArrayInputStream( data, 0, length )));
			
			long	version = ((Long)map.get( "ver" )).longValue();
			long	type	= ((Long)map.get( "type" )).longValue();
			
			InetAddress	originator_address = originator.getAddress();
			
			if ( map.get( "explicit" ) != null ){
				
				addInstanceSupport( originator_address, false );
			}
			
			AZOtherInstanceImpl	instance = AZOtherInstanceImpl.decode( originator_address, (Map)map.get( "orig" ));
			
			if ( type == MT_ALIVE ){
				
				checkAdd( instance );
				
			}else if ( type == MT_BYE ){
				
				checkRemove( instance );
				
			}else{
				
				checkAdd( instance );
				
				Map	body = (Map)map.get( "body" );
				
				if ( type == MT_REQUEST ){
					
					String	originator_id	= instance.getID();
					
					if ( !originator_id.equals( my_instance.getID())){
						
						Map	reply = requestReceived( instance, body );
					
						if ( reply != null ){
						
							reply.put( "oid", originator_id.getBytes());
							reply.put( "rid", body.get( "rid" ));
							
							sendMessage( MT_REPLY, reply, originator );
						}
					}
				}else if ( 	type == MT_REPLY ){
					
					String	originator_id	= new String((byte[])body.get( "oid" ));
					
					if ( originator_id.equals( my_instance.getID())){
						
						long req_id = ((Long)body.get("rid")).longValue();
						
						try{
							this_mon.enter();
							
							for (int i=0;i<requests.size();i++){
								
								request	req = (request)requests.get(i);
								
								if ( req.getID() == req_id ){
									
									req.addReply( instance, body );
								}
							}
						}finally{
							
							this_mon.exit();
						}
					}
				}
			}
		}catch( Throwable e ){
			
			Debug.printStackTrace(e);
		}
	}
	

	protected Map
	requestReceived(
		AZInstance		instance,
		Map				body )
	{
		// System.out.println( "received result: " + ST + "/" + AL );
		

		long	type = ((Long)body.get( "type")).longValue();
		
		if ( type == MT_REQUEST_SEARCH ){
			
			return( new HashMap());
			
		}else if ( type == MT_REQUEST_TRACK ){
							
			byte[]	hash = (byte[])body.get( "hash" );
			
			boolean	seed = ((Long)body.get( "seed" )).intValue() == 1;
			
			List	dms = core.getGlobalManager().getDownloadManagers();
			
			Iterator	it = dms.iterator();
			
			DownloadManager	matching_dm = null;
			
			try{
				while( it.hasNext()){
					
					DownloadManager	dm = (DownloadManager)it.next();
					
					TOTorrent	torrent = dm.getTorrent();
					
					if ( torrent == null ){
						
						continue;
					}
					
					byte[]	sha1_hash = (byte[])dm.getData( "AZInstanceManager::sha1_hash" );
					
					if ( sha1_hash == null ){			

						sha1_hash	= new SHA1Simple().calculateHash( torrent.getHash());
						
						dm.setData( "AZInstanceManager::sha1_hash", sha1_hash );
					}
					
					if ( Arrays.equals( hash, sha1_hash )){
						
						matching_dm	= dm;
						
						break;
					}
				}
			}catch( Throwable e ){
				
				Debug.printStackTrace(e);
			}
			
			if ( matching_dm == null ){
				
				return( null );
			}
			
			int	dm_state = matching_dm.getState();
			
			if ( dm_state == DownloadManager.STATE_ERROR || dm_state == DownloadManager.STATE_STOPPED ){
				
				return( null );
			}
							
			try{		
				informTracked( 
					new trackedInstance( instance, DownloadManagerImpl.getDownloadStatic( matching_dm ), seed ));
					
			}catch( Throwable e ){
					
				Debug.printStackTrace(e);
			}
			
			Map	reply = new HashMap();
			
			// XXX include DND?  I don't know
			reply.put( "seed", new Long( matching_dm.isDownloadComplete(true)?1:0));		
			
			return( reply );
			
		}else{
			
			return( null );
		}
	}
	
	public void
	interfaceChanged(
		NetworkInterface	network_interface )
	{
		sendAlive();
	}
	
	protected AZOtherInstanceImpl
	checkAdd(
		AZOtherInstanceImpl	inst )
	{
		if ( inst.getID().equals( my_instance.getID())){
			
			return( inst );
		}
		
		boolean	added 	= false;
		boolean	changed	= false;
		
		try{
			this_mon.enter();
			
			AZOtherInstanceImpl	existing = (AZOtherInstanceImpl)other_instances.get( inst.getID());
			
			if ( existing == null ){
				
				added	= true;
			
				other_instances.put( inst.getID(), inst );
								
			}else{
								
				changed = existing.update( inst );

				inst	= existing;
			}
		}finally{
			
			this_mon.exit();
		}
		
		if ( added ){
			
			informAdded( inst );
			
		}else if ( changed ){
			
			informChanged( inst );
		}
		
		return( inst );
	}
	
	protected void
	checkRemove(
		AZOtherInstanceImpl	inst )
	{
		if ( inst.getID().equals( my_instance.getID())){
			
			return;
		}
		
		boolean	removed = false;
		
		try{
			this_mon.enter();
			
			removed = other_instances.remove( inst.getID()) != null;
			
		}finally{
			
			this_mon.exit();
		}
		
		if ( removed ){
			
			informRemoved( inst );
		}
	}
	
	public AZInstance
	getMyInstance()
	{
		return( my_instance );
	}
	

⌨️ 快捷键说明

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