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

📄 aesocksproxyconnectionimpl.java

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

import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.HostNameToIPResolver;
import org.gudy.azureus2.core3.util.HostNameToIPResolverListener;

import com.aelitis.azureus.core.proxy.*;
import com.aelitis.azureus.core.proxy.socks.*;

/**
 * @author parg
 *
 */

public class 
AESocksProxyConnectionImpl
	implements AESocksProxyConnection, AEProxyConnectionListener
{
	private static final LogIDs LOGID = LogIDs.NET;
	public static final boolean	TRACE	= false;
	
	protected AESocksProxyImpl		proxy;
	protected AEProxyConnection		connection;
	protected boolean				disable_dns_lookups;
	
	protected SocketChannel			source_channel;
	
	protected int					socks_version;
	
	protected AESocksProxyPlugableConnection	plugable_connection;
	
	protected
	AESocksProxyConnectionImpl(
		AESocksProxyImpl						_proxy,
		AESocksProxyPlugableConnectionFactory	_connection_factory,
		AEProxyConnection						_connection )
	
		throws IOException
	{
		proxy		= _proxy;
		connection	= _connection;
		
		connection.addListener( this );
		
		source_channel	= connection.getSourceChannel();
		
		try{
			plugable_connection	= _connection_factory.create( this );
		
			if ( TRACE ){
				Logger.log(new LogEvent(LOGID, "AESocksProxyProcessor: " + getName()));
			}
		}catch( AEProxyException e ){
			
			throw( new IOException( e.getMessage()));
		}
	}
	
	public AESocksProxy
	getProxy()
	{
		return( proxy );
	}
	
	public void
	setDelegate(
		AESocksProxyPlugableConnection	target )
	{
		plugable_connection = target;
	}
	
	protected String
	getName()
	{
		String	name = connection.getName() + ", ver = " + socks_version;
					
		name += plugable_connection.getName();
		
		return( name );
	}
	
	protected AEProxyState
	getInitialState()
	{
		return( new proxyStateVersion());
	}
	
	public void
	connectionClosed(
		AEProxyConnection	con )
	{
		try{
			if ( plugable_connection != null ){
				
				plugable_connection.close();
			}
			
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
		}
	}
	
	public boolean
	isClosed()
	{
		return( connection.isClosed());
	}
	
	public AEProxyConnection
	getConnection()
	{
		return( connection );
	}
	
	public void
	disableDNSLookups()
	{
		disable_dns_lookups	= true;
	}
	
	public void
	enableDNSLookups()
	{
		disable_dns_lookups = false;
	}
	
	public void
	close()
	
		throws IOException
	{
		new proxyStateClose();
	}
	
	protected class
	proxyStateVersion
		extends AESocksProxyState
	{
		protected
		proxyStateVersion()
		{
			super( AESocksProxyConnectionImpl.this );
			
			connection.setReadState( this );
			
			buffer	= ByteBuffer.allocate(1);
		}
		
		protected boolean
		readSupport(
			SocketChannel 		sc )
		
			throws IOException
		{
			int	len = sc.read( buffer );
			
			if ( len == 0 ){
				
				return( false );
				
			}else if ( len == -1 ){
				
				throw( new IOException( "read channel shutdown" ));
			}
			
			if ( buffer.hasRemaining()){
				
				return( true );
			}
			
			buffer.flip();
			
			int	version	= buffer.get();
			
			if ( version == 5 ){
			
				new proxyStateV5MethodNumber();
				
			}else if ( version == 4 ){
				
				new proxyStateV4Request();
				
			}else{
				
				throw( new IOException( "Unsupported version " + version ));

			}
			
			return( true );
		}
	}
	
		// V4
	
	protected class
	proxyStateV4Request
		extends AESocksProxyState
	{
		boolean		got_header;
		
		protected int		port;
		protected byte[]	address;
		
		protected
		proxyStateV4Request()
		{
			super( AESocksProxyConnectionImpl.this );
			
			connection.setReadState( this );

			buffer	= ByteBuffer.allocate(7);
		}
	
		protected boolean
		readSupport(
			SocketChannel 		sc )
		
			throws IOException
		{
			/*
			+----+----+----+----+----+----+----+----+----+----+....+----+
			| VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
			+----+----+----+----+----+----+----+----+----+----+....+----+
			# of bytes:	   1    1      2              4           variable       1
			*/

			int	len = sc.read( buffer );
			
			if ( len == 0 ){
				
				return( false );
				
			}else if ( len == -1 ){
				
				throw( new IOException( "read channel shutdown" ));
			}
						
			if ( buffer.hasRemaining()){
				
				return( true );
			}
			
			buffer.flip();
			
			if ( got_header ){
				
				if ( buffer.get() == (byte)0){
				
						// end of play
		
					if (	address[0] == 0 &&
							address[1] == 0 &&
							address[2] == 0 &&
							address[3] != 0 ){
						
							// socks 4a
						
						new proxyStateV4aRequest( port );
						
					}else{
							
						socks_version	= 4;
						
						plugable_connection.connect( 
								new AESocksProxyAddressImpl( "", InetAddress.getByAddress( address ), port ));
						
					}
				}else{
				
					// drop the user id byte
					
					buffer.flip();
					
				}
			}else{
				
				got_header	= true;
				
				byte	command	= buffer.get();
				
				if ( command != 1 ){
					
					throw( new IOException( "SocksV4: only CONNECT supported" ));
				}
				
				port = (((int)buffer.get() & 0xff) << 8 ) + ((int)buffer.get() & 0xff);

				address = new byte[4];
				
				for (int i=0;i<address.length;i++){
				
					address[i] = buffer.get();
				}
				
					// prepare for user id
				
				buffer = ByteBuffer.allocate(1);
			}
			
			return( true );
		}
	}
	
	protected class
	proxyStateV4aRequest
		extends AESocksProxyState
	{
		protected String	dns_address;
		protected int		port;
		
		protected
		proxyStateV4aRequest(
			int		_port )
		{
			super( AESocksProxyConnectionImpl.this );
			
			port		= _port;
			dns_address	= "";
			
			connection.setReadState( this );

			buffer	= ByteBuffer.allocate(1);
		}
	
		protected boolean
		readSupport(
			final SocketChannel 		sc )
		
			throws IOException
		{
				// dns name follows, null terminated

			int	len = sc.read( buffer );
			
			if ( len == 0 ){
				
				return( false );
				
			}else if ( len == -1 ){
				
				throw( new IOException( "read channel shutdown" ));
			}
			
			
			if ( buffer.hasRemaining()){
				
				return( true );
			}
			
			buffer.flip();
							
			byte data = buffer.get();
			
			if ( data == 0 ){
				
				if ( disable_dns_lookups ){
					
					socks_version	= 4;
					
					plugable_connection.connect( new AESocksProxyAddressImpl( dns_address, null, port ));

				}else{
					final String	f_dns_address	= dns_address;
					
					connection.cancelReadSelect( sc );
					
					HostNameToIPResolver.addResolverRequest(
						dns_address,
						new HostNameToIPResolverListener()
						{
							public void
							hostNameResolutionComplete(
								InetAddress	address )
							{
								try{
									socks_version	= 4;
									
									plugable_connection.connect( new AESocksProxyAddressImpl( f_dns_address, address, port ));
		
										// re-activate the read select suspended while resolving
									
									connection.requestReadSelect( sc );
									
								}catch ( IOException e ){
									
									connection.failed(e);
								}
							}
						});		
				}
			}else{
				
				dns_address += (char)data;
				
				if ( dns_address.length() > 4096 ){
					
					throw( new IOException( "DNS name too long" ));
				}
				
					// ready for next byte
				
				buffer.flip();
			}
			
			return( true );
		}
	}
	
	protected class
	proxyStateV4Reply
		extends AESocksProxyState
	{
		protected
		proxyStateV4Reply()
		
			throws IOException
		{		
			super( AESocksProxyConnectionImpl.this );
			
			/*
			+----+----+----+----+----+----+----+----+
			| VN | CD | DSTPORT |      DSTIP        |
			+----+----+----+----+----+----+----+----+
			# of bytes:	   1    1      2              4
			*/

			connection.setWriteState( this );
			
			byte[]	addr = plugable_connection.getLocalAddress().getAddress();
			int		port = plugable_connection.getLocalPort();
			
			buffer	= ByteBuffer.wrap(
					new byte[]{	(byte)0,(byte)90,
								(byte)((port>>8)&0xff), (byte)(port&0xff),
								addr[0],addr[1],addr[2],addr[3]});
					
			
			write( source_channel );
		}
		
		protected boolean
		writeSupport(
			SocketChannel 		sc )
		
			throws IOException
		{
			int	len = sc.write( buffer );
			
			if ( buffer.hasRemaining()){
				
				connection.requestWriteSelect( sc );
				
			}else{
	
				plugable_connection.relayData();
			}
			
			return( len > 0 );
		}
	}
	
		// V5
	
	protected class
	proxyStateV5MethodNumber
		extends AESocksProxyState
	{
		
		protected
		proxyStateV5MethodNumber()
		{
			super( AESocksProxyConnectionImpl.this );
			
			connection.setReadState( this );

			buffer	= ByteBuffer.allocate(1);
		}
		
		protected boolean
		readSupport(
			SocketChannel 		sc )
		
			throws IOException
		{
			int	len = sc.read( buffer );
			
			if ( len == 0 ){

⌨️ 快捷键说明

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