0
|
1 package net.sourceforge.jsocks;
|
|
2 import java.io.IOException;
|
|
3 import java.io.InputStream;
|
|
4 import java.io.InterruptedIOException;
|
|
5 import java.io.OutputStream;
|
|
6 import java.net.InetAddress;
|
|
7 import java.net.Socket;
|
|
8 import java.net.UnknownHostException;
|
|
9
|
|
10 /**
|
|
11 Abstract class Proxy, base for classes Socks4Proxy and Socks5Proxy.
|
|
12 Defines methods for specifying default proxy, to be
|
|
13 used by all classes of this package.
|
|
14 */
|
|
15
|
|
16 public abstract class Proxy {
|
|
17
|
|
18 //Data members
|
|
19 //protected InetRange directHosts = new InetRange();
|
|
20
|
|
21 protected InetAddress proxyIP = null;
|
|
22 protected String proxyHost = null;
|
|
23 protected int proxyPort;
|
|
24 protected Socket proxySocket = null;
|
|
25
|
|
26 protected InputStream in;
|
|
27 protected OutputStream out;
|
|
28
|
|
29 protected int version;
|
|
30
|
|
31 protected Proxy chainProxy = null;
|
|
32
|
|
33
|
|
34 //Protected static/class variables
|
|
35 protected static Proxy defaultProxy = null;
|
|
36
|
|
37 //Constructors
|
|
38 //====================
|
|
39 Proxy(String proxyHost, int proxyPort) throws UnknownHostException {
|
|
40 this.proxyHost = proxyHost;
|
|
41 this.proxyIP = InetAddress.getByName(proxyHost);
|
|
42 this.proxyPort = proxyPort;
|
|
43 }
|
|
44
|
|
45 Proxy(Proxy chainProxy, InetAddress proxyIP, int proxyPort) {
|
|
46 this.chainProxy = chainProxy;
|
|
47 this.proxyIP = proxyIP;
|
|
48 this.proxyPort = proxyPort;
|
|
49 }
|
|
50
|
|
51 Proxy(InetAddress proxyIP, int proxyPort) {
|
|
52 this.proxyIP = proxyIP;
|
|
53 this.proxyPort = proxyPort;
|
|
54 }
|
|
55
|
|
56 Proxy(Proxy p) {
|
|
57 this.proxyIP = p.proxyIP;
|
|
58 this.proxyPort = p.proxyPort;
|
|
59 this.version = p.version;
|
|
60 }
|
|
61
|
|
62 //Public instance methods
|
|
63 //========================
|
|
64
|
|
65 /**
|
|
66 Get the port on which proxy server is running.
|
|
67 * @return Proxy port.
|
|
68 */
|
|
69 public int getPort() {
|
|
70 return proxyPort;
|
|
71 }
|
|
72 /**
|
|
73 Get the ip address of the proxy server host.
|
|
74 * @return Proxy InetAddress.
|
|
75 */
|
|
76 public InetAddress getInetAddress() {
|
|
77 return proxyIP;
|
|
78 }
|
|
79
|
|
80 /**
|
|
81 Get string representation of this proxy.
|
|
82 * @returns string in the form:proxyHost:proxyPort \t Version versionNumber
|
|
83 */
|
|
84 public String toString() {
|
|
85 return ("" + proxyIP.getHostName() + ":" + proxyPort + "\tVersion " + version);
|
|
86 }
|
|
87
|
|
88
|
|
89 //Public Static(Class) Methods
|
|
90 //==============================
|
|
91
|
|
92 /**
|
|
93 * Sets SOCKS4 proxy as default.
|
|
94 @param hostName Host name on which SOCKS4 server is running.
|
|
95 @param port Port on which SOCKS4 server is running.
|
|
96 @param user Username to use for communications with proxy.
|
|
97 */
|
|
98 public static void setDefaultProxy(String hostName, int port, String user)
|
|
99 throws UnknownHostException {
|
|
100 defaultProxy = new Socks4Proxy(hostName, port, user);
|
|
101 }
|
|
102
|
|
103 /**
|
|
104 * Sets SOCKS4 proxy as default.
|
|
105 @param ipAddress Host address on which SOCKS4 server is running.
|
|
106 @param port Port on which SOCKS4 server is running.
|
|
107 @param user Username to use for communications with proxy.
|
|
108 */
|
|
109 public static void setDefaultProxy(InetAddress ipAddress, int port,
|
|
110 String user) {
|
|
111 defaultProxy = new Socks4Proxy(ipAddress, port, user);
|
|
112 }
|
|
113 /**
|
|
114 * Sets SOCKS5 proxy as default.
|
|
115 * Default proxy only supports no-authentication.
|
|
116 @param hostName Host name on which SOCKS5 server is running.
|
|
117 @param port Port on which SOCKS5 server is running.
|
|
118 */
|
|
119 public static void setDefaultProxy(String hostName, int port)
|
|
120 throws UnknownHostException {
|
|
121 defaultProxy = new Socks5Proxy(hostName, port);
|
|
122 }
|
|
123 /**
|
|
124 * Sets SOCKS5 proxy as default.
|
|
125 * Default proxy only supports no-authentication.
|
|
126 @param ipAddress Host address on which SOCKS5 server is running.
|
|
127 @param port Port on which SOCKS5 server is running.
|
|
128 */
|
|
129 public static void setDefaultProxy(InetAddress ipAddress, int port) {
|
|
130 defaultProxy = new Socks5Proxy(ipAddress, port);
|
|
131 }
|
|
132 /**
|
|
133 * Sets default proxy.
|
|
134 @param p Proxy to use as default proxy.
|
|
135 */
|
|
136 public static void setDefaultProxy(Proxy p) {
|
|
137 defaultProxy = p;
|
|
138 }
|
|
139
|
|
140 /**
|
|
141 Get current default proxy.
|
|
142 * @return Current default proxy, or null if none is set.
|
|
143 */
|
|
144 public static Proxy getDefaultProxy() {
|
|
145 return defaultProxy;
|
|
146 }
|
|
147
|
|
148 /**
|
|
149 Parses strings in the form: host[:port:user:password], and creates
|
|
150 proxy from information obtained from parsing.
|
|
151 <p>
|
|
152 Defaults: port = 1080.<br>
|
|
153 If user specified but not password, creates Socks4Proxy, if user
|
|
154 not specified creates Socks5Proxy, if both user and password are
|
|
155 speciefied creates Socks5Proxy with user/password authentication.
|
|
156 @param proxy_entry String in the form host[:port:user:password]
|
|
157 @return Proxy created from the string, null if entry was somehow
|
|
158 invalid(host unknown for example, or empty string)
|
|
159 */
|
|
160 public static Proxy parseProxy(String proxy_entry) {
|
|
161 String proxy_host;
|
|
162 int proxy_port = 1080;
|
|
163 String proxy_user = null;
|
|
164 String proxy_password = null;
|
|
165 Proxy proxy;
|
|
166 java.util.StringTokenizer st = new java.util.StringTokenizer(
|
|
167 proxy_entry, ":");
|
|
168
|
|
169 if (st.countTokens() < 1) return null;
|
|
170
|
|
171 proxy_host = st.nextToken();
|
|
172
|
|
173 if (st.hasMoreTokens())
|
|
174 try {
|
|
175 proxy_port = Integer.parseInt(st.nextToken().trim());
|
|
176 }
|
|
177 catch (NumberFormatException nfe) {}
|
|
178
|
|
179 if (st.hasMoreTokens())
|
|
180 proxy_user = st.nextToken();
|
|
181
|
|
182 if (st.hasMoreTokens())
|
|
183 proxy_password = st.nextToken();
|
|
184
|
|
185 try {
|
|
186 if (proxy_user == null)
|
|
187 proxy = new Socks5Proxy(proxy_host, proxy_port);
|
|
188 else if (proxy_password == null)
|
|
189 proxy = new Socks4Proxy(proxy_host, proxy_port, proxy_user);
|
|
190 else {
|
|
191 proxy = new Socks5Proxy(proxy_host, proxy_port);
|
|
192 /*
|
|
193 UserPasswordAuthentication upa = new UserPasswordAuthentication(
|
|
194 proxy_user, proxy_password);
|
|
195
|
|
196 ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa);
|
|
197 */
|
|
198 }
|
|
199 }
|
|
200 catch (UnknownHostException uhe) {
|
|
201 return null;
|
|
202 }
|
|
203
|
|
204 return proxy;
|
|
205 }
|
|
206
|
|
207
|
|
208 //Protected Methods
|
|
209 //=================
|
|
210
|
|
211 protected void startSession()throws SocksException {
|
|
212 try {
|
|
213 proxySocket = new Socket(proxyIP, proxyPort);
|
|
214 in = proxySocket.getInputStream();
|
|
215 out = proxySocket.getOutputStream();
|
|
216 }
|
|
217 catch (SocksException se) {
|
|
218 throw se;
|
|
219 }
|
|
220 catch (IOException io_ex) {
|
|
221 throw new SocksException(SOCKS_PROXY_IO_ERROR, "" + io_ex);
|
|
222 }
|
|
223 }
|
|
224
|
|
225 protected abstract Proxy copy();
|
|
226 protected abstract ProxyMessage formMessage(int cmd, InetAddress ip, int port);
|
|
227 protected abstract ProxyMessage formMessage(int cmd, String host, int port)
|
|
228 throws UnknownHostException;
|
|
229 protected abstract ProxyMessage formMessage(InputStream in)
|
|
230 throws SocksException,
|
|
231 IOException;
|
|
232
|
|
233
|
|
234 protected ProxyMessage connect(InetAddress ip, int port)
|
|
235 throws SocksException {
|
|
236 try {
|
|
237 startSession();
|
|
238 ProxyMessage request = formMessage(SOCKS_CMD_CONNECT,
|
|
239 ip, port);
|
|
240 return exchange(request);
|
|
241 }
|
|
242 catch (SocksException se) {
|
|
243 endSession();
|
|
244 throw se;
|
|
245 }
|
|
246 }
|
|
247 protected ProxyMessage connect(String host, int port)
|
|
248 throws UnknownHostException, SocksException {
|
|
249 try {
|
|
250 startSession();
|
|
251 ProxyMessage request = formMessage(SOCKS_CMD_CONNECT,
|
|
252 host, port);
|
|
253 return exchange(request);
|
|
254 }
|
|
255 catch (SocksException se) {
|
|
256 endSession();
|
|
257 throw se;
|
|
258 }
|
|
259 }
|
|
260
|
|
261 protected ProxyMessage bind(InetAddress ip, int port)
|
|
262 throws SocksException {
|
|
263 try {
|
|
264 startSession();
|
|
265 ProxyMessage request = formMessage(SOCKS_CMD_BIND,
|
|
266 ip, port);
|
|
267 return exchange(request);
|
|
268 }
|
|
269 catch (SocksException se) {
|
|
270 endSession();
|
|
271 throw se;
|
|
272 }
|
|
273 }
|
|
274 protected ProxyMessage bind(String host, int port)
|
|
275 throws UnknownHostException, SocksException {
|
|
276 try {
|
|
277 startSession();
|
|
278 ProxyMessage request = formMessage(SOCKS_CMD_BIND,
|
|
279 host, port);
|
|
280 return exchange(request);
|
|
281 }
|
|
282 catch (SocksException se) {
|
|
283 endSession();
|
|
284 throw se;
|
|
285 }
|
|
286 }
|
|
287
|
|
288 protected ProxyMessage accept()
|
|
289 throws IOException, SocksException {
|
|
290 ProxyMessage msg;
|
|
291
|
|
292 try {
|
|
293 msg = formMessage(in);
|
|
294 }
|
|
295 catch (InterruptedIOException iioe) {
|
|
296 throw iioe;
|
|
297 }
|
|
298 catch (IOException io_ex) {
|
|
299 endSession();
|
|
300 throw new SocksException(SOCKS_PROXY_IO_ERROR, "While Trying accept:"
|
|
301 + io_ex);
|
|
302 }
|
|
303
|
|
304 return msg;
|
|
305 }
|
|
306
|
|
307 protected ProxyMessage udpAssociate(InetAddress ip, int port)
|
|
308 throws SocksException {
|
|
309 try {
|
|
310 startSession();
|
|
311 ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
|
|
312 ip, port);
|
|
313
|
|
314 if (request != null)
|
|
315 return exchange(request);
|
|
316 }
|
|
317 catch (SocksException se) {
|
|
318 endSession();
|
|
319 throw se;
|
|
320 }
|
|
321
|
|
322 //Only get here if request was null
|
|
323 endSession();
|
|
324 throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
|
|
325 "This version of proxy does not support UDP associate, use version 5");
|
|
326 }
|
|
327 protected ProxyMessage udpAssociate(String host, int port)
|
|
328 throws UnknownHostException, SocksException {
|
|
329 try {
|
|
330 startSession();
|
|
331 ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
|
|
332 host, port);
|
|
333
|
|
334 if (request != null) return exchange(request);
|
|
335 }
|
|
336 catch (SocksException se) {
|
|
337 endSession();
|
|
338 throw se;
|
|
339 }
|
|
340
|
|
341 //Only get here if request was null
|
|
342 endSession();
|
|
343 throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
|
|
344 "This version of proxy does not support UDP associate, use version 5");
|
|
345 }
|
|
346
|
|
347
|
|
348 protected void endSession() {
|
|
349 try {
|
|
350 if (proxySocket != null) proxySocket.close();
|
|
351
|
|
352 proxySocket = null;
|
|
353 }
|
|
354 catch (IOException io_ex) {
|
|
355 }
|
|
356 }
|
|
357
|
|
358 /**
|
|
359 *Sends the request to SOCKS server
|
|
360 */
|
|
361 protected void sendMsg(ProxyMessage msg)throws SocksException,
|
|
362 IOException {
|
|
363 msg.write(out);
|
|
364 }
|
|
365
|
|
366 /**
|
|
367 * Reads the reply from the SOCKS server
|
|
368 */
|
|
369 protected ProxyMessage readMsg()throws SocksException,
|
|
370 IOException {
|
|
371 return formMessage(in);
|
|
372 }
|
|
373 /**
|
|
374 *Sends the request reads reply and returns it
|
|
375 *throws exception if something wrong with IO
|
|
376 *or the reply code is not zero
|
|
377 */
|
|
378 protected ProxyMessage exchange(ProxyMessage request)
|
|
379 throws SocksException {
|
|
380 ProxyMessage reply;
|
|
381
|
|
382 try {
|
|
383 request.write(out);
|
|
384 reply = formMessage(in);
|
|
385 }
|
|
386 catch (SocksException s_ex) {
|
|
387 throw s_ex;
|
|
388 }
|
|
389 catch (IOException ioe) {
|
|
390 throw(new SocksException(SOCKS_PROXY_IO_ERROR, "" + ioe));
|
|
391 }
|
|
392
|
|
393 return reply;
|
|
394 }
|
|
395
|
|
396
|
|
397 //Private methods
|
|
398 //===============
|
|
399
|
|
400
|
|
401 //Constants
|
|
402
|
|
403 public static final int SOCKS_SUCCESS = 0;
|
|
404 public static final int SOCKS_FAILURE = 1;
|
|
405 public static final int SOCKS_BADCONNECT = 2;
|
|
406 public static final int SOCKS_BADNETWORK = 3;
|
|
407 public static final int SOCKS_HOST_UNREACHABLE = 4;
|
|
408 public static final int SOCKS_CONNECTION_REFUSED = 5;
|
|
409 public static final int SOCKS_TTL_EXPIRE = 6;
|
|
410 public static final int SOCKS_CMD_NOT_SUPPORTED = 7;
|
|
411 public static final int SOCKS_ADDR_NOT_SUPPORTED = 8;
|
|
412
|
|
413 public static final int SOCKS_NO_PROXY = 1 << 16;
|
|
414 public static final int SOCKS_PROXY_NO_CONNECT = 2 << 16;
|
|
415 public static final int SOCKS_PROXY_IO_ERROR = 3 << 16;
|
|
416 public static final int SOCKS_AUTH_NOT_SUPPORTED = 4 << 16;
|
|
417 public static final int SOCKS_AUTH_FAILURE = 5 << 16;
|
|
418 public static final int SOCKS_JUST_ERROR = 6 << 16;
|
|
419
|
|
420 public static final int SOCKS_DIRECT_FAILED = 7 << 16;
|
|
421 public static final int SOCKS_METHOD_NOTSUPPORTED = 8 << 16;
|
|
422
|
|
423
|
|
424 public static final int SOCKS_CMD_CONNECT = 0x1;
|
|
425 static final int SOCKS_CMD_BIND = 0x2;
|
|
426 static final int SOCKS_CMD_UDP_ASSOCIATE = 0x3;
|
|
427
|
|
428 }
|