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

📄 sockssocketimpl.java

📁 Java编写的GUI聊天工具
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
		return port;
	}
	private static final byte[] getPort(byte[] b, int offset)
	{
		byte[] port=new byte[2];
		port[0]=b[offset];
		port[1]=b[offset+1];
		return port;
	}
	private static final int getPortValue(
		byte[] b,int offset)
	{
		int port=b[offset]<0?(short)b[offset]+256:b[offset];
		port<<=8;
		offset++;
		port+=b[offset]<0?(short)b[offset]+256:b[offset];
		return port;
	}
	private static final InetAddress getInetAddress(
		int addressType,byte[] b,int offset)throws IOException
	{
		String host;
		switch(addressType)
		{
		case IP_V4:
			StringBuffer destinationHost=new StringBuffer(16);
			for(int i=offset;i<offset+4;i++)
			{
				destinationHost.append(b[i]<0?(short)(b[i]+256):(short)b[i]);
				if(i<offset+3)
					destinationHost.append('.');
			}
			host=destinationHost.toString();
			break;
		case DOMAINNAME:
			int length=b[offset++];
			if(length<0)length+=256;
			host=new String(b,offset,length);
			break;
		case IP_V6:
			throw new IOException("Error: IPV6 is not supported.");
		default:
			throw new IOException("Error: Unknown IP address type.");
		}
		return InetAddress.getByName(host);
	}




	/**
	 * Setup a SOCKS connection to the remote host through the SOCKS server
	 */
	private synchronized void doSOCKSConnect()throws IOException
	{
		if(remoteAddress==null || remotePort==null)
			throw new IOException("Error: You Cann't connect without defining the IP address and port of remote host.");

		for(int i=0;i<5;i++)//Try fivet time since the proxy server is possible very busy.
		{
			try
			{
				if(stream)
				{
					clientSocket=new Socket(proxyAddress,proxyPort,localAddress,localport);
					localAddress=clientSocket.getLocalAddress();
					localport=clientSocket.getLocalPort();
				}
				else//DatagramSocket
				{
					clientSocket=new Socket(proxyAddress,proxyPort,localAddress,0);
				}
				clientSocket.setSoTimeout(timeout);
				break;
			}
			catch(IOException e)
			{
				if(i<4)
				{
					try
					{
						Thread.sleep(200);
					}
					catch (InterruptedException ie){} 
				}
				else
				{
					close();
					throw e;
				}
			}
		}

		switch(version)
		{
		case SOCKS_VERSION_4A:
			request_of_V4A(COMMAND_CONNECT,remoteAddress,remotePort,remoteHost);
			reply_of_V4A(false);
			break;
		case SOCKS_VERSION_5:
			methodSelection_of_V5();
			if(stream)
			{
				request_of_V5(COMMAND_CONNECT,NULL,remoteAddressType,remoteAddress,remotePort);
				reply_of_V5(COMMAND_CONNECT,false);
			}
			else
			{
//				request_of_V5(COMMAND_UDP_ASSOCIATE,INTERFACE_REQUEST,remoteAddressType,remoteAddress,remotePort);
				request_of_V5(COMMAND_UDP_ASSOCIATE,NULL,remoteAddressType,remoteAddress,remotePort);
				reply_of_V5(COMMAND_UDP_ASSOCIATE,false);
			}
			break;
		}
	}
	private void request_of_V4A(int command,
		byte[] destinationAddress,byte[] destinationPort,
		byte[] destinationHost)throws IOException
	{
		outputBuffer.reset();
		outputBuffer.write(SOCKS_VERSION_4A);
		outputBuffer.write(command);
		outputBuffer.write(destinationPort);
		outputBuffer.write(destinationAddress);
		if(password!=null)
			outputBuffer.write(password);//It's the USERID in SOCKS4A.
		outputBuffer.write(NULL);//terminate in NULL byte
		if(destinationAddress[0]==0)//Such a destination IP address is inadmissible
		{
			outputBuffer.write(destinationHost);
			outputBuffer.write(NULL);//terminate in NULL byte
		}

		OutputStream out=clientSocket.getOutputStream();
		outputBuffer.writeTo(out);
		out.flush();
	}

	private int serverBoundAddressType;
	private InetAddress serverBoundAddress=null;
	private int serverBoundPort=0;
	private int remoteBoundAddressType;
	private byte[] remoteBoundAddress=null;
	private byte[] remoteBoundPort=null;
	/**
	 * Set command for the specific SOCKS proxy serer.
	 */
	private int command=COMMAND_CONNECT;

	private void reply_of_V4A(boolean isGetRemoteBoundParamaters)throws IOException
	{
		int count;
		String errorMessage=null;
		byte[] buffer=new byte[8];
		InputStream in=clientSocket.getInputStream();
		while((count= in.read(buffer)) >= 0)
		{
			if(count==0)
				continue;
			else if(count<8 || buffer[0]!=NULL)
				errorMessage="failed to parse the malformed reply from the socks server.";
			else
			{
				switch(buffer[1])
				{
				case REQUEST_GRANTED:
					if(isGetRemoteBoundParamaters)
					{
						remoteBoundPort=getPort(buffer,2);
						remoteBoundAddress=getAddress(IP_V4,buffer,4);
					}
					else
					{
						serverBoundPort=getPortValue(buffer,2);
						serverBoundAddress=getInetAddress(IP_V4,buffer,4);
					}
					break;
				case REQUEST_REJECTED:
					errorMessage="request rejected or failed";
					break;
				case REQUEST_REJECTED_NO_IDENTD:
					errorMessage="request rejected becasue SOCKS server cannot connect to identd on the client";
					break;
				case REQUEST_REJECTED_DIFF_IDENTS:
					errorMessage="request rejected because the client program and identd report different user-ids";
					break;
				}
			}
			if(errorMessage!=null)
			{
				close();
				throw new IOException("("+proxyAddress.getHostAddress()+":"+proxyPort+") "+errorMessage);
			}
			break;
		}

		if(command!=COMMAND_BIND)return;
		{
		}
	}private String Username_AND_Password_Authentication_of_V5()throws IOException
	{
		outputBuffer.reset();
		outputBuffer.write(0x01);
		if(username==null)
			outputBuffer.write(0x0);
		else
		{
			outputBuffer.write(username.length);
			outputBuffer.write(username);
		}
		if(password==null)
			outputBuffer.write(0x0);
		else
		{
			outputBuffer.write(password.length);
			outputBuffer.write(password);
		}

		OutputStream out=clientSocket.getOutputStream();
		outputBuffer.writeTo(out);
		out.flush();

		int count;
		String errorMessage=null;
		byte[] buffer=new byte[2];
		InputStream in=clientSocket.getInputStream();
		while((count= in.read(buffer)) >= 0)
		{
			if(count==0)
				continue;
			else if(count<2 || buffer[0]!=0x01)
			{
				errorMessage="failed to parse the authentication reply from the socks server.";
			}
			else if(buffer[1]!=0x0)
			{
				errorMessage="failed to through the authentication reply from the socks server.";
			}
			if(errorMessage!=null)
			{
				close();
				throw new IOException("("+proxyAddress.getHostAddress()+":"+proxyPort+") "+errorMessage);
			}
			break;
		}
		return errorMessage;
	}
	private void methodSelection_of_V5()throws IOException
	{
		outputBuffer.reset();
		outputBuffer.write(SOCKS_VERSION_5);

		//Now only complement the negotiation methods of
		// NO_AUTHENTICATION_REQUIRED and USERNAME_AND_PASSWORD
		outputBuffer.write(2);//the number of method identifier octets that appear in the METHODS field
		outputBuffer.write(NO_AUTHENTICATION_REQUIRED);
//		outputBuffer.write(GSSAPI);
		outputBuffer.write(USERNAME_AND_PASSWORD);
//		outputBuffer.write(CHAP);

		OutputStream out=clientSocket.getOutputStream();
		outputBuffer.writeTo(out);
		out.flush();

		int method;
		if(username!=null || password!=null)
			method=USERNAME_AND_PASSWORD;
		else
			method=NO_AUTHENTICATION_REQUIRED;

		int count;
		String errorMessage=null;
		byte[] buffer=new byte[2];
		InputStream in=clientSocket.getInputStream();
		while((count= in.read(buffer)) >= 0)
		{
			if(count==0)
				continue;
			else if(count<2 || buffer[0]!=SOCKS_VERSION_5)
				errorMessage="failed to parse the reply from the socks server.";
			else
			{
				switch(buffer[1])
				{
				case NO_AUTHENTICATION_REQUIRED:
					break;
				case GSSAPI:
					errorMessage="GSSAPI negotiation hasn't been still complemented.";
					break;
				case USERNAME_AND_PASSWORD:
					errorMessage=Username_AND_Password_Authentication_of_V5();
					break;
				case CHAP:
					errorMessage="CHAP negotiation hasn't been still complemented.";
					break;
				case (byte)NO_ACCEPTABLE_METHODS:
					errorMessage="No acceptable negotiation method.";
					break;
				default:
					errorMessage="The negotiation method with a METHOD number of "+(int)buffer[1]+" hasn't been still complemented.";
					break;
				}
			}
			if(errorMessage!=null)
			{
				close();
				throw new IOException("("+proxyAddress.getHostAddress()+":"+proxyPort+") "+errorMessage);
			}
			break;
		}
	}
	private void request_of_V5(int command,int flag,
		int addressType,byte[] destinationAddress,byte[] destinationPort)throws IOException
	{
		outputBuffer.reset();

		outputBuffer.write(SOCKS_VERSION_5);
		outputBuffer.write(command);
		outputBuffer.write(flag);//command dependent flag (defaults to X'00')
		if(command!=COMMAND_UDP_ASSOCIATE)
		{
			outputBuffer.write(addressType);
			if(addressType==DOMAINNAME)
				outputBuffer.write(destinationAddress.length);
			outputBuffer.write(destinationAddress);
			outputBuffer.write(destinationPort);
		}
		else
		{
			outputBuffer.write(IP_V4);
			outputBuffer.write(getAddress(localAddress));
			outputBuffer.write(getPort(localport));
		}

		OutputStream out=clientSocket.getOutputStream();
		outputBuffer.writeTo(out);
		out.flush();
	}
	private void reply_of_V5(int command,boolean isGetRemoteBoundParamaters)throws IOException
	{
		int count;
		String errorMessage=null;
		byte[] buffer=new byte[64];
		InputStream in=clientSocket.getInputStream();
		while((count= in.read(buffer)) >= 0)
		{
			if(count==0)
				continue;
			else if(count<8 || buffer[0]!=SOCKS_VERSION_5)
				errorMessage="failed to parse the reply from the socks server.";
			else
			{
				switch(buffer[1])
				{
				case SUCCEEDED:
					int tempBoundAddressType=buffer[3];
					int offset=4;
					InetAddress tempBoundAddress=getInetAddress(tempBoundAddressType,buffer,offset);
					switch(tempBoundAddressType)
					{
					case DOMAINNAME:
						offset+=(buffer[offset+1]<0?buffer[offset+1]+256:buffer[offset+1])+1;
						break;
					case IP_V4:
						offset+=4;
						break;
//					case IP_V6:
					default:
						offset+=16;
					}

					int tempBoundPort=getPortValue(buffer,offset);
					if(isGetRemoteBoundParamaters)
					{
//						remoteBoundAddressType=tempBoundAddressType;
//						remoteBoundAddress=tempBoundAddress;
//						remoteBoundPort=tempBoundPort;
					}
					else
					{
						serverBoundAddressType=tempBoundAddressType;
						serverBoundAddress=tempBoundAddress;
						serverBoundPort=tempBoundPort;
					}
					break;
				case FAILURE:
					errorMessage="general SOCKS server failure";
					break;
				case NOT_ALLOWED:
					errorMessage="connection not allowed by ruleset";
					break;
				case NETWORK_UNREACHABLE:
					errorMessage="Network unreachable";
					break;
				case HOST_UNREACHABLE:
					errorMessage="Host unreachable";
					break;
				case REFUSED:
					errorMessage="Connection refused";
					break;
				case TTL_EXPIRED:
					errorMessage="TTL expired";
					break;
				case COMMAND_NOT_SUPPORTED:
					errorMessage="Command not supported";
					break;
				case ADDRESS_TYPE_NOT_SUPPORTED:
					errorMessage="Address type not supported";
					break;
				case INVALID_ADDRESS:
					errorMessage="Invalid address";
					break;
				default:
					errorMessage="unknown reply code ("+(int)buffer[1]+")";
					break;
				}
			}
			if(errorMessage!=null)
			{
				close();
				throw new IOException("("+proxyAddress.getHostAddress()+":"+proxyPort+") "+errorMessage);
			}
			break;
		}
	}

	/**
	 * Close the SocksSocket() connection to the SOCKS server.
	 *
	 * @exception  IOException  if an I/O error occurs when closing this socket.
	 */
	protected void close() throws IOException
	{
		if (clientSocket != null)
		{
			try
			{
				clientSocket.close();
			}
			catch(java.io.IOException e)
			{
			}
			clientSocket=null;
		}
		else if(clientDatagramSocket!=null)
		{
			clientDatagramSocket.close();
			clientDatagramSocket=null;
		}

	}

	/*
	 * instance variable for SO_TIMEOUT
	 */
	private int timeout=15000;//A timeout of zero is interpreted as an infinite timeout.
	/*
	 * instance variable for TCP_NODELAY
	 */
	private boolean tcpNoDelay=false;

⌨️ 快捷键说明

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