Mercurial > 510Connectbot
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 } |