comparison src/net/sourceforge/jsocks/Socks5Message.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
comparison
equal deleted inserted replaced
-1:000000000000 0:0ce5cc452d02
1 package net.sourceforge.jsocks;
2
3 import java.io.DataInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.OutputStream;
7 import java.net.InetAddress;
8 import java.net.UnknownHostException;
9
10 /**
11 SOCKS5 request/response message.
12 */
13
14 public class Socks5Message extends ProxyMessage {
15 /** Address type of given message*/
16 public int addrType;
17
18 byte[] data;
19
20 /**
21 Server error response.
22 @param cmd Error code.
23 */
24 public Socks5Message(int cmd) {
25 super(cmd, null, 0);
26 data = new byte[3];
27 data[0] = SOCKS_VERSION; //Version.
28 data[1] = (byte)cmd; //Reply code for some kind of failure.
29 data[2] = 0; //Reserved byte.
30 }
31
32 /**
33 Construct client request or server response.
34 @param cmd - Request/Response code.
35 @param ip - IP field.
36 @paarm port - port field.
37 */
38 public Socks5Message(int cmd, InetAddress ip, int port) {
39 super(cmd, ip, port);
40 this.host = ip == null ? "0.0.0.0" : ip.getHostName();
41 this.version = SOCKS_VERSION;
42 byte[] addr;
43
44 if (ip == null) {
45 addr = new byte[4];
46 addr[0] = addr[1] = addr[2] = addr[3] = 0;
47 }
48 else
49 addr = ip.getAddress();
50
51 addrType = addr.length == 4 ? SOCKS_ATYP_IPV4
52 : SOCKS_ATYP_IPV6;
53 data = new byte[6 + addr.length];
54 data[0] = (byte) SOCKS_VERSION; //Version
55 data[1] = (byte) command; //Command
56 data[2] = (byte) 0; //Reserved byte
57 data[3] = (byte) addrType; //Address type
58 //Put Address
59 System.arraycopy(addr, 0, data, 4, addr.length);
60 //Put port
61 data[data.length - 2] = (byte)(port >> 8);
62 data[data.length - 1] = (byte)(port);
63 }
64
65
66 /**
67 Construct client request or server response.
68 @param cmd - Request/Response code.
69 @param hostName - IP field as hostName, uses ADDR_TYPE of HOSTNAME.
70 @paarm port - port field.
71 */
72 public Socks5Message(int cmd, String hostName, int port) {
73 super(cmd, null, port);
74 this.host = hostName;
75 this.version = SOCKS_VERSION;
76 //System.out.println("Doing ATYP_DOMAINNAME");
77 addrType = SOCKS_ATYP_DOMAINNAME;
78 byte addr[] = hostName.getBytes();
79 data = new byte[7 + addr.length];
80 data[0] = (byte) SOCKS_VERSION; //Version
81 data[1] = (byte) command; //Command
82 data[2] = (byte) 0; //Reserved byte
83 data[3] = (byte) SOCKS_ATYP_DOMAINNAME; //Address type
84 data[4] = (byte) addr.length; //Length of the address
85 //Put Address
86 System.arraycopy(addr, 0, data, 5, addr.length);
87 //Put port
88 data[data.length - 2] = (byte)(port >> 8);
89 data[data.length - 1] = (byte)(port);
90 }
91
92 /**
93 Initialises Message from the stream. Reads server response from
94 given stream.
95 @param in Input stream to read response from.
96 @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
97 if any error with protocol occurs.
98 @throws IOException If any error happens with I/O.
99 */
100 public Socks5Message(InputStream in) throws SocksException,
101 IOException {
102 this(in, true);
103 }
104
105 /**
106 Initialises Message from the stream. Reads server response or client
107 request from given stream.
108
109 @param in Input stream to read response from.
110 @param clinetMode If true read server response, else read client request.
111 @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
112 reading in client mode, or if any error with protocol occurs.
113 @throws IOException If any error happens with I/O.
114 */
115 public Socks5Message(InputStream in, boolean clientMode)throws SocksException,
116 IOException {
117 read(in, clientMode);
118 }
119
120
121 /**
122 Initialises Message from the stream. Reads server response from
123 given stream.
124 @param in Input stream to read response from.
125 @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
126 if any error with protocol occurs.
127 @throws IOException If any error happens with I/O.
128 */
129 public void read(InputStream in) throws SocksException,
130 IOException {
131 read(in, true);
132 }
133
134
135 /**
136 Initialises Message from the stream. Reads server response or client
137 request from given stream.
138
139 @param in Input stream to read response from.
140 @param clinetMode If true read server response, else read client request.
141 @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
142 reading in client mode, or if any error with protocol occurs.
143 @throws IOException If any error happens with I/O.
144 */
145 public void read(InputStream in, boolean clientMode) throws SocksException,
146 IOException {
147 data = null;
148 ip = null;
149 DataInputStream di = new DataInputStream(in);
150 version = di.readUnsignedByte();
151 command = di.readUnsignedByte();
152
153 if (clientMode && command != 0)
154 throw new SocksException(command);
155
156 @SuppressWarnings("unused")
157 int reserved = di.readUnsignedByte();
158 addrType = di.readUnsignedByte();
159 byte addr[];
160
161 switch (addrType) {
162 case SOCKS_ATYP_IPV4:
163 addr = new byte[4];
164 di.readFully(addr);
165 host = bytes2IPV4(addr, 0);
166 break;
167
168 case SOCKS_ATYP_IPV6:
169 addr = new byte[SOCKS_IPV6_LENGTH];//I believe it is 16 bytes,huge!
170 di.readFully(addr);
171 host = bytes2IPV6(addr, 0);
172 break;
173
174 case SOCKS_ATYP_DOMAINNAME:
175 //System.out.println("Reading ATYP_DOMAINNAME");
176 addr = new byte[di.readUnsignedByte()];//Next byte shows the length
177 di.readFully(addr);
178 host = new String(addr);
179 break;
180
181 default:
182 throw(new SocksException(Proxy.SOCKS_JUST_ERROR));
183 }
184
185 port = di.readUnsignedShort();
186
187 if (addrType != SOCKS_ATYP_DOMAINNAME && doResolveIP) {
188 try {
189 ip = InetAddress.getByName(host);
190 }
191 catch (UnknownHostException uh_ex) {
192 }
193 }
194 }
195
196 /**
197 Writes the message to the stream.
198 @param out Output stream to which message should be written.
199 */
200 public void write(OutputStream out)throws SocksException,
201 IOException {
202 if (data == null) {
203 Socks5Message msg;
204
205 if (addrType == SOCKS_ATYP_DOMAINNAME)
206 msg = new Socks5Message(command, host, port);
207 else {
208 if (ip == null) {
209 try {
210 ip = InetAddress.getByName(host);
211 }
212 catch (UnknownHostException uh_ex) {
213 throw new SocksException(Proxy.SOCKS_JUST_ERROR);
214 }
215 }
216
217 msg = new Socks5Message(command, ip, port);
218 }
219
220 data = msg.data;
221 }
222
223 out.write(data);
224 }
225
226 /**
227 Returns IP field of the message as IP, if the message was created
228 with ATYP of HOSTNAME, it will attempt to resolve the hostname,
229 which might fail.
230 @throws UnknownHostException if host can't be resolved.
231 */
232 public InetAddress getInetAddress() throws UnknownHostException {
233 if (ip != null) return ip;
234
235 return (ip = InetAddress.getByName(host));
236 }
237
238 /**
239 Returns string representation of the message.
240 */
241 public String toString() {
242 String s =
243 "Socks5Message:" + "\n" +
244 "VN " + version + "\n" +
245 "CMD " + command + "\n" +
246 "ATYP " + addrType + "\n" +
247 "ADDR " + host + "\n" +
248 "PORT " + port + "\n";
249 return s;
250 }
251
252
253 /**
254 *Wether to resolve hostIP returned from SOCKS server
255 *that is wether to create InetAddress object from the
256 *hostName string
257 */
258 static public boolean resolveIP() { return doResolveIP;}
259
260 /**
261 *Wether to resolve hostIP returned from SOCKS server
262 *that is wether to create InetAddress object from the
263 *hostName string
264 *@param doResolve Wether to resolve hostIP from SOCKS server.
265 *@return Previous value.
266 */
267 static public boolean resolveIP(boolean doResolve) {
268 boolean old = doResolveIP;
269 doResolveIP = doResolve;
270 return old;
271 }
272
273 /*
274 private static final void debug(String s){
275 if(DEBUG)
276 System.out.print(s);
277 }
278 private static final boolean DEBUG = false;
279 */
280
281 //SOCKS5 constants
282 public static final int SOCKS_VERSION = 5;
283
284 public static final int SOCKS_ATYP_IPV4 = 0x1; //Where is 2??
285 public static final int SOCKS_ATYP_DOMAINNAME = 0x3; //!!!!rfc1928
286 public static final int SOCKS_ATYP_IPV6 = 0x4;
287
288 public static final int SOCKS_IPV6_LENGTH = 16;
289
290 static boolean doResolveIP = true;
291
292 }