Mercurial > 510Connectbot
diff src/net/sourceforge/jsocks/Socks4Message.java @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children | 205ee2873330 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/net/sourceforge/jsocks/Socks4Message.java Thu May 22 10:41:19 2014 -0700 @@ -0,0 +1,182 @@ +package net.sourceforge.jsocks; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + SOCKS4 Reply/Request message. +*/ + +public class Socks4Message extends ProxyMessage { + + private byte[] msgBytes; + private int msgLength; + + /** + * Server failed reply, cmd command for failed request + */ + public Socks4Message(int cmd) { + super(cmd, null, 0); + this.user = null; + msgLength = 2; + msgBytes = new byte[2]; + msgBytes[0] = (byte) 0; + msgBytes[1] = (byte) command; + } + + /** + * Server successfull reply + */ + public Socks4Message(int cmd, InetAddress ip, int port) { + this(0, cmd, ip, port, null); + } + + /** + * Client request + */ + public Socks4Message(int cmd, InetAddress ip, int port, String user) { + this(SOCKS_VERSION, cmd, ip, port, user); + } + + /** + * Most general constructor + */ + public Socks4Message(int version, int cmd, + InetAddress ip, int port, String user) { + super(cmd, ip, port); + this.user = user; + this.version = version; + msgLength = user == null ? 8 : 9 + user.length(); + msgBytes = new byte[msgLength]; + msgBytes[0] = (byte) version; + msgBytes[1] = (byte) command; + msgBytes[2] = (byte)(port >> 8); + msgBytes[3] = (byte) port; + byte[] addr; + + if (ip != null) + addr = ip.getAddress(); + else { + addr = new byte[4]; + addr[0] = addr[1] = addr[2] = addr[3] = 0; + } + + System.arraycopy(addr, 0, msgBytes, 4, 4); + + if (user != null) { + byte[] buf = user.getBytes(); + System.arraycopy(buf, 0, msgBytes, 8, buf.length); + msgBytes[msgBytes.length - 1 ] = 0; + } + } + + /** + *Initialise from the stream + *If clientMode is true attempts to read a server response + *otherwise reads a client request + *see read for more detail + */ + public Socks4Message(InputStream in, boolean clientMode) throws IOException { + msgBytes = null; + read(in, clientMode); + } + + @Override + public void read(InputStream in) throws IOException { + read(in, true); + } + + @Override + public void read(InputStream in, boolean clientMode) throws IOException { + boolean mode4a = false; + DataInputStream d_in = new DataInputStream(in); + version = d_in.readUnsignedByte(); + command = d_in.readUnsignedByte(); + + if (clientMode && command != REPLY_OK) { + String errMsg; + + if (command > REPLY_OK && command < REPLY_BAD_IDENTD) + errMsg = replyMessage[command - REPLY_OK]; + else + errMsg = "Unknown Reply Code"; + + throw new SocksException(command, errMsg); + } + + port = d_in.readUnsignedShort(); + byte[] addr = new byte[4]; + d_in.readFully(addr); + + if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] != 0) + mode4a = true; + else { + ip = bytes2IP(addr); + host = ip.getHostName(); + } + + if (!clientMode) { + StringBuilder sb = new StringBuilder(); + int b; + + while ((b = in.read()) != 0) + sb.append((char) b); + + user = sb.toString(); + + if (mode4a) { + sb.setLength(0); + + while ((b = in.read()) != 0) + sb.append((char) b); + + host = sb.toString(); + } + } + } + @Override + public void write(OutputStream out) throws IOException { + if (msgBytes == null) { + Socks4Message msg = new Socks4Message(version, command, ip, port, user); + msgBytes = msg.msgBytes; + msgLength = msg.msgLength; + } + + out.write(msgBytes); + } + + //Class methods + static InetAddress bytes2IP(byte[] addr) { + String s = bytes2IPV4(addr, 0); + + try { + return InetAddress.getByName(s); + } + catch (UnknownHostException uh_ex) { + return null; + } + } + + //Constants + + static final String[] replyMessage = { + "Request Granted", + "Request Rejected or Failed", + "Failed request, can't connect to Identd", + "Failed request, bad user name" + }; + + static final int SOCKS_VERSION = 4; + + public final static int REQUEST_CONNECT = 1; + public final static int REQUEST_BIND = 2; + + public final static int REPLY_OK = 90; + public final static int REPLY_REJECTED = 91; + public final static int REPLY_NO_CONNECT = 92; + public final static int REPLY_BAD_IDENTD = 93; + +}