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

📄 sockssocketimpl.java

📁 Java编写的GUI聊天工具
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
package com.jeeva.chatclient;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;

import java.net.Socket;
import java.net.SocketImpl;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import java.util.Properties;

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.io.FileDescriptor;
import java.net.SocketAddress;
/**
 *
 *  SocksSocketImpl: A Socket implementation class support SOCKS4A & SOCKS5
 *
 *  @version 1.1a,
 *
 *  @author  Jeeva S (vavjeeva@yahoo.com)
 *
 *
 */

/**
 *  SocksSocketImpl: A Socket Implementation class support SOCKS4A & SOCKS5
 *
 *  <A HREF="http://www.socks.nec.com/socksprot.html">SOCKS References:</A><BR>
 *	 <DD>[1] <A HREF="http://www.socks.nec.com/protocol/socks4.protocol">SOCKS 4 Protocol</A><BR>
 *	 <DD>[2] <A HREF="http://www.socks.nec.com/protocol/socks4a.protocol">SOCKS 4A: A Simple Extension to SOCKS 4 Protocol</A><BR>
 *	 <DD>[3] <A HREF="//http://www.socks.nec.com/rfc/rfc1928.txt">RFC1928 SOCKS Protocol Version 5</A><BR>
 *	 <DD>[4] <A HREF="//http://www.socks.nec.com/rfc/rfc1929.txt">RFC1929 Username/Password Authentication for SOCKS V5</A></DL></DD>
 *	 <DD>[5] <A HREF="//http://www.socks.nec.com/draft/draft-ietf-aft-socks-pro-v5-04.txt">SOCKS Protocol Version 5 (22 Feb 1999)</A></DL></DD>
 */

class SocksSocketImpl extends SocketImpl implements SocksSocketConstants
{
	/*
	 *  a boolean indicating whether this is a stream socket or a datagram socket.
	 *  If the stream argument is true, this creates a stream socket. If the stream argument is
	 *  false, it creates a datagram socket. 
	 */
	private boolean stream=true;
	/*
	 * The Socket between local host and SOCKS proxy server when there is a proxy server.
	 * The Socket between local host and remote host when there isn't a proxy server.
	 */
	private Socket clientSocket=null;
	/*
	 * the direct DatagramSocket communication between local host and remote host.
	 */
	private DatagramSocket clientDatagramSocket=null;

	/*
	 * The IP address of the SOCKS proxy server.
	 */
	private InetAddress proxyAddress=null;
	/**
	 * Returns the value of this socket's <code>proxy address</code> field.
	 *
	 * @return  the value of this socket's <code>proxy address</code> field.
	 * @see	 java.net.SocketImpl#address
	 */
	protected InetAddress getProxyAddress()
	{
		return proxyAddress;
	}
	/*
	 * The port number on the SOCKS proxy serer.
	 */
	private int proxyPort=SOCKS_PORT;
	/**
	 * Returns the value of this socket's <code>proxy port</code> field.
	 *
	 * @return  the value of this socket's <code>proxy port</code> field.
	 */
	protected int getProxyPort()
	{
		return proxyPort;
	}

	/*
	 * The IP address of the local end of this socket.
	 * instance variable for SO_BINDADDR
	 */
	/*
	 */
	private InetAddress localAddress=null;
	/**
	 * Returns the value of this socket's <code>proxy address</code> field.
	 *
	 * @return  the value of this socket's <code>proxy address</code> field.
	 * @see	 java.net.SocketImpl#address
	 */
	protected InetAddress getLocalAddress()
	{
		return localAddress;
	}
	/**
	 * Returns the value of this socket's <code>localport</code> field.
	 *
	 * @return  the value of this socket's <code>localport</code> field.
	 * @see	 java.net.SocketImpl#localport
	 */
	protected int getLocalPort()
	{
		return localport;
	}
	/**
	 * Returns the value of this socket's <code>address</code> field.
	 *
	 * @return  the value of this socket's <code>address</code> field.
	 * @see	 java.net.SocketImpl#address
	 */
	protected InetAddress getInetAddress()
	{
		return address;
	}

	/**
	 * Returns the value of this socket's <code>port</code> field.
	 *
	 * @return  the value of this socket's <code>port</code> field.
	 * @see	 java.net.SocketImpl#port
	 */
	protected int getPort()
	{
		return port;
	}


	/*
	 * An ojbect for output buffer
	 */
	private ByteArrayOutputStream outputBuffer;

	protected SocksSocketImpl(){}
	protected SocksSocketImpl(boolean stream)
	{
		this.stream=stream;
	}
	
	protected void sendUrgentData(int data)
	{
		/*********Do Nothing ********/	
	}
	
	protected SocksSocketImpl(String proxyHost,int proxyPort)throws java.net.UnknownHostException
	{
		this(InetAddress.getByName(proxyHost),proxyPort,null,true);
	}
	protected SocksSocketImpl(InetAddress proxyAddress,int proxyPort,Properties properties)
	{
		this(proxyAddress,proxyPort,properties,true);
	}
	protected SocksSocketImpl(InetAddress proxyAddress,int proxyPort,Properties properties,boolean stream)
	{
		this.proxyAddress=proxyAddress;
		this.proxyPort=proxyPort;
		this.stream=stream;
		if(proxyAddress!=null)
			outputBuffer= new ByteArrayOutputStream(1024);
		if(properties!=null)
			initProperties(properties);
		if(!stream)//Set version to SOCKS_VERSION_5 since SOCKS_VERSION_4A cann't support datagram socket
			version=SOCKS_VERSION_5;
	}
	
	private void initProperties(Properties properties)
	{
		String value=properties.getProperty(SocksSocket.USERNAME);
		if(value!=null)username=value.getBytes();
		value=properties.getProperty(SocksSocket.PASSWORD);
		if(value!=null)password=value.getBytes();
		value=properties.getProperty(SocksSocket.VERSION);
		if(value!=null)
		{
			try
			{
				version=Integer.parseInt(value)==SOCKS_VERSION_5?SOCKS_VERSION_5:SOCKS_VERSION_4A;
			}
			catch(NumberFormatException nfe){}
		}
	}



	/**
	 * Creates either a stream or a datagram socket. 
	 * Creates a socket with a boolean that specifies whether this
	 * is a stream socket (true) or an unconnected UDP socket (false).
	 *
	 * @param	stream   if <code>true</code>, create a stream socket;
	 *					  otherwise, create a datagram socket.
	 * @exception  IOException  if an I/O error occurs while creating the
	 *			   socket.
	 */
	protected void create(boolean stream) throws IOException
	{
		//Nothing since it's always a socket connection between local host and proxy server.
	}

	/**
	 * Binds this socket to the specified port number flag the specified host. 
	 *
	 * @param	address   the IP address of the specified host.
	 * @param	port   the port number.
	 * @exception  IOException  if an I/O error occurs when binding this socket.
	 */
	protected void bind(InetAddress address, int port)throws IOException
	{
		this.localAddress=address;
		this.localport=port;
	}

	/**
	 * Connects this stream socket to the specified port flag the named host. 
	 *
	 * @param	host   the name of the remote host.
	 * @param	port   the port number.
	 * @exception  IOException  if an I/O error occurs when connecting to the
	 *			   remote host.
	 */
	protected void connect(String host, int port)throws UnknownHostException, IOException
	{
		try
		{
			if(proxyAddress==null)//Direct Socket Connection
			{
				clientSocket=new Socket(InetAddress.getByName(host),port,localAddress,localport);
				localAddress=clientSocket.getLocalAddress();
			}
			else//SOCKS Connection
			{
				initRemoteHost(host,port);
				doSOCKSConnect();
			}
		}
		catch (IOException e)
		{
			close();
			throw e;
		}
	}

	/**
	 * Connects this stream or datagram socket to the specified port number flag the specified host.
	 *
	 * @param	address   the IP address of the remote host.
	 * @param	port	 the port number.
	 * @exception  IOException  if an I/O error occurs when attempting a
	 *			   connection.
	 */
	protected void connect(InetAddress address, int port) throws IOException
	{
		try
		{
			if(stream)// Stream socket connection
			{
				boolean isConnected=clientSocket!=null;
				if(isConnected)return;
				if(proxyAddress==null)// Direct Stream Socket Connection
				{
					clientSocket=new Socket(address,port,localAddress,localport);
					localAddress=clientSocket.getLocalAddress();
					localport=clientSocket.getLocalPort();
				}
				else//SOCKS Connection
				{
					initRemoteHost(address,port);
					doSOCKSConnect();
				}
			}
			else//datagram socket connection
			{
				this.address=address;
				this.port=port;
				boolean isConnected=clientDatagramSocket!=null;
				if(!isConnected)
				{
					clientDatagramSocket=new DatagramSocket(localport,localAddress);
					localAddress=clientDatagramSocket.getLocalAddress();
					localport=clientDatagramSocket.getLocalPort();
				}
				if(proxyAddress==null)// Direct datagram socket connection
				{
					clientDatagramSocket.connect(address,port);
				}
				else//SOCKS Connection
				{
					initRemoteHost(address,port);
					if(!isConnected)
						doSOCKSConnect();
				}
			}
		}
		catch (IOException e)
		{
			close();
			throw e;
		}
	}
	
	protected void connect(SocketAddress address, int port) throws IOException
	{
		/**********Do Nothing **********/	
	}
	/**
	 * Returns an input stream for this socket.
	 *
	 * @return	 a stream for reading from this socket.
	 * @exception  IOException  if an I/O error occurs when creating the
	 *			   input stream.
	 */
	protected synchronized InputStream getInputStream() throws IOException
	{
		if(clientSocket!=null)
			return clientSocket.getInputStream();
		else
			throw new IOException("Error: Try to access an unconnected or closed Socks connection.");
	}

	/**
	 * Returns an output stream for this socket.
	 *
	 * @return	 an output stream for writing to this socket.
	 * @exception  IOException  if an I/O error occurs when creating the
	 *			   output stream.
	 */
	protected synchronized OutputStream getOutputStream() throws IOException
	{
		if(clientSocket!=null)
			return clientSocket.getOutputStream();
		else
			throw new IOException("Error: Try to access an unconnected or closed Socks connection.");
	}

	/**
	 * Returns the number of bytes that can be read from this socket
	 * without blocking.
	 *
	 * @return	 the number of bytes that can be read from this socket
	 *			 without blocking.
	 * @exception  IOException  if an I/O error occurs when determining the
	 *			   number of bytes available.
	 */
	protected synchronized int available() throws IOException
	{
		return getInputStream().available();
	}


	/**
	 * Set the appropriate SOCKS version for the specific SOCKS proxy serer.
	 */
	private int version=SOCKS_VERSION_5;

	/**
	 * Set username for the specific SOCKS proxy serer.
	 */
	private byte[] username=null;

	/**
	 * Set password for the specific SOCKS proxy serer.
	 */
	private byte[] password=null;

	/**
	 * Set the IP address and port number of the remote end of this socket.
	 */private byte[] remoteHost=null;
	private byte[] remotePort=null;
	private byte[] remoteAddress=null;
	private int remoteAddressType;
	private void initRemoteHost(String host,int port)throws UnknownHostException
	{
		try
		{
			this.port = port;
			remotePort=getPort(port);
			remoteAddressType=IP_V4;
			remoteHost=host.getBytes();
			this.address= InetAddress.getByName(host);
			remoteAddress=getAddress(address);
		}
		catch(Exception uhe)//Use it to catch security exception
//		catch(UnknownHostException uhe)
		{
			switch(version)
			{
			case SOCKS_VERSION_4A:
				remoteAddress=new byte[4];
				//Such a destination IP address is inadmissible
//				remoteAddress[0]=remoteAddress[1]=remoteAddress[2]=0;
				remoteAddress[3]=(byte)0xFF;
				break;
			case SOCKS_VERSION_5:
				remoteAddress=remoteHost;
				remoteAddressType=DOMAINNAME;
				break;
			}
		}
	}
	private void initRemoteHost(InetAddress address,int port)
	{
		this.address= address;
		this.port = port;
		remoteAddress=getAddress(address);
		remotePort=getPort(port);
		remoteAddressType=IP_V4;
	}
	private static final byte[] getAddress(InetAddress ia)
	{
		if(ia==null)
			return new byte[4];
		else
			return ia.getAddress();

/*		int addressIntegerValue=ia.hashCode();
		byte[] address=new byte[4];
		for(int i=3;i>=0;i--)
		{
			address[i]=(byte)(addressIntegerValue&0xFF);
			addressIntegerValue>>>=8;
		}
		return address;*/
	}
	private static final byte[] getAddress(int addressType, byte[] b, int offset)
	{
		int length;
		switch(addressType)
		{
		case DOMAINNAME:
			length=b[offset];
			offset++;
			break;
		case IP_V4:
			length=4;
			break;
//		case IP_V6:
		default://
			length=16;
			break;
		}
		byte[] address=new byte[length];
		for(int i=0;i<length;i++,offset++)
			address[i]=b[offset];
		return address;
	}
	private static final byte[] getPort(int p)
	{
		byte[] port=new byte[2];
		port[0]=(byte)((p>>>8)&0xFF);
		port[1]=(byte)(p&0xFF);

⌨️ 快捷键说明

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