aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/net/sourceforge/jsocks/Proxy.java
blob: 381c0a06bdbc595b2d0b2e0bcb1882979842adce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
package net.sourceforge.jsocks;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
  Abstract class Proxy, base for classes Socks4Proxy and Socks5Proxy.
  Defines methods for specifying default proxy, to be
  used by all classes of this package.
*/

public abstract class Proxy{

//Data members
   //protected InetRange directHosts = new InetRange();

   protected InetAddress proxyIP = null;
   protected String proxyHost = null;
   protected int proxyPort;
   protected Socket proxySocket = null;

   protected InputStream in;
   protected OutputStream out;

   protected int version;

   protected Proxy chainProxy = null;


//Protected static/class variables
   protected static Proxy defaultProxy = null;

//Constructors
//====================
	Proxy(String proxyHost, int proxyPort) throws UnknownHostException {
		this.proxyHost = proxyHost;
		this.proxyIP = InetAddress.getByName(proxyHost);
		this.proxyPort = proxyPort;
	}

   Proxy(Proxy chainProxy,InetAddress proxyIP,int proxyPort){
      this.chainProxy = chainProxy;
      this.proxyIP = proxyIP;
      this.proxyPort = proxyPort;
   }

   Proxy(InetAddress proxyIP,int proxyPort){
      this.proxyIP = proxyIP;
      this.proxyPort = proxyPort;
   }

   Proxy(Proxy p){
      this.proxyIP = p.proxyIP;
      this.proxyPort = p.proxyPort;
      this.version = p.version;
   }

//Public instance methods
//========================

   /**
      Get the port on which proxy server is running.
    * @return Proxy port.
    */
   public int getPort(){
     return proxyPort;
   }
   /**
      Get the ip address of the proxy server host.
    * @return Proxy InetAddress.
    */
   public InetAddress getInetAddress(){
     return proxyIP;
   }

    /**
       Get string representation of this proxy.
     * @returns string in the form:proxyHost:proxyPort \t Version versionNumber
     */
    public String toString(){
       return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version);
    }


//Public Static(Class) Methods
//==============================

   /**
    * Sets SOCKS4 proxy as default.
      @param hostName Host name on which SOCKS4 server is running.
      @param port Port on which SOCKS4 server is running.
      @param user Username to use for communications with proxy.
    */
   public static void setDefaultProxy(String hostName,int port,String user)
                             throws UnknownHostException{
      defaultProxy = new Socks4Proxy(hostName,port,user);
   }

   /**
    * Sets SOCKS4 proxy as default.
      @param ipAddress Host address on which SOCKS4 server is running.
      @param port Port on which SOCKS4 server is running.
      @param user Username to use for communications with proxy.
    */
   public static void setDefaultProxy(InetAddress ipAddress,int port,
                                      String user){
      defaultProxy = new Socks4Proxy(ipAddress,port,user);
   }
   /**
    * Sets SOCKS5 proxy as default.
    * Default proxy only supports no-authentication.
      @param hostName Host name on which SOCKS5 server is running.
      @param port Port on which SOCKS5 server is running.
    */
   public static void setDefaultProxy(String hostName,int port)
                             throws UnknownHostException{
      defaultProxy = new Socks5Proxy(hostName,port);
   }
   /**
    * Sets SOCKS5 proxy as default.
    * Default proxy only supports no-authentication.
      @param ipAddress Host address on which SOCKS5 server is running.
      @param port Port on which SOCKS5 server is running.
    */
   public static void setDefaultProxy(InetAddress ipAddress,int port){
      defaultProxy = new Socks5Proxy(ipAddress,port);
   }
   /**
    * Sets default proxy.
      @param p Proxy to use as default proxy.
    */
   public static void setDefaultProxy(Proxy p){
     defaultProxy = p;
   }

   /**
      Get current default proxy.
    * @return Current default proxy, or null if none is set.
    */
   public static Proxy getDefaultProxy(){
     return defaultProxy;
   }

   /**
     Parses strings in the form: host[:port:user:password], and creates
     proxy from information obtained from parsing.
     <p>
     Defaults: port = 1080.<br>
     If user specified but not password, creates Socks4Proxy, if user
     not specified creates Socks5Proxy, if both user and password are
     speciefied creates Socks5Proxy with user/password authentication.
     @param proxy_entry String in the form host[:port:user:password]
     @return Proxy created from the string, null if entry was somehow
             invalid(host unknown for example, or empty string)
   */
   public static Proxy parseProxy(String proxy_entry){

      String proxy_host;
      int proxy_port = 1080;
      String proxy_user = null;
      String proxy_password = null;
      Proxy proxy;

      java.util.StringTokenizer st = new java.util.StringTokenizer(
                                         proxy_entry,":");
      if(st.countTokens() < 1) return null;

      proxy_host = st.nextToken();
      if(st.hasMoreTokens())
         try{
           proxy_port = Integer.parseInt(st.nextToken().trim());
         }catch(NumberFormatException nfe){}

      if(st.hasMoreTokens())
         proxy_user = st.nextToken();

      if(st.hasMoreTokens())
         proxy_password = st.nextToken();

      try{
         if(proxy_user == null)
           proxy = new Socks5Proxy(proxy_host,proxy_port);
         else if(proxy_password == null)
           proxy = new Socks4Proxy(proxy_host,proxy_port,proxy_user);
         else{
           proxy = new Socks5Proxy(proxy_host,proxy_port);
           /*
           UserPasswordAuthentication upa = new UserPasswordAuthentication(
                                            proxy_user, proxy_password);

           ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa);
           */
         }
      }catch(UnknownHostException uhe){
         return null;
      }

      return proxy;
   }


//Protected Methods
//=================

   protected void startSession()throws SocksException{
       try{
         proxySocket = new Socket(proxyIP,proxyPort);
         in = proxySocket.getInputStream();
         out = proxySocket.getOutputStream();
       }catch(SocksException se){
         throw se;
       }catch(IOException io_ex){
         throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex);
       }
   }

   protected abstract Proxy copy();
   protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port);
   protected abstract ProxyMessage formMessage(int cmd,String host,int port)
             throws UnknownHostException;
   protected abstract ProxyMessage formMessage(InputStream in)
             throws SocksException,
                    IOException;
   

   protected ProxyMessage connect(InetAddress ip,int port)
             throws SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_CONNECT,
			                     ip,port);
         return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
   }
   protected ProxyMessage connect(String host,int port)
             throws UnknownHostException,SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_CONNECT,
			                     host,port);
         return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
   }

   protected ProxyMessage bind(InetAddress ip,int port)
             throws SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_BIND,
				             ip,port);
         return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
   }
   protected ProxyMessage bind(String host,int port)
             throws UnknownHostException,SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_BIND,
				             host,port);
         return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
   }

   protected ProxyMessage accept()
             throws IOException,SocksException{
      ProxyMessage msg;
      try{
         msg = formMessage(in);
      }catch(InterruptedIOException iioe){
         throw iioe;
      }catch(IOException io_ex){
         endSession();
         throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:"
         +io_ex);
      }
      return msg;
   }

   protected ProxyMessage udpAssociate(InetAddress ip,int port)
             throws SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
				             ip,port);
         if(request != null)
           return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
      //Only get here if request was null
      endSession();
      throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
      "This version of proxy does not support UDP associate, use version 5");
   }
   protected ProxyMessage udpAssociate(String host,int port)
             throws UnknownHostException,SocksException{
      try{
         startSession();
         ProxyMessage request  = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
				             host,port);
         if(request != null) return exchange(request);
      }catch(SocksException se){
         endSession();
         throw se;
      }
      //Only get here if request was null
      endSession();
      throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
      "This version of proxy does not support UDP associate, use version 5");
   }


   protected void endSession(){
      try{
         if(proxySocket!=null) proxySocket.close();
         proxySocket = null;
      }catch(IOException io_ex){
      }
   }

   /**
    *Sends the request to SOCKS server
    */
   protected void sendMsg(ProxyMessage msg)throws SocksException,
                                                  IOException{
      msg.write(out);
   }

   /** 
    * Reads the reply from the SOCKS server
    */
   protected ProxyMessage readMsg()throws SocksException,
                                          IOException{
      return formMessage(in);
   }
   /**
    *Sends the request reads reply and returns it
    *throws exception if something wrong with IO
    *or the reply code is not zero
    */
   protected ProxyMessage exchange(ProxyMessage request)
                           throws SocksException{
      ProxyMessage reply;
      try{
         request.write(out);
         reply = formMessage(in);
      }catch(SocksException s_ex){
         throw s_ex;
      }catch(IOException ioe){
         throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe));
      }
      return reply;
   }


//Private methods
//===============


//Constants

   public static final int SOCKS_SUCCESS		=0;
   public static final int SOCKS_FAILURE		=1;
   public static final int SOCKS_BADCONNECT		=2;
   public static final int SOCKS_BADNETWORK		=3;
   public static final int SOCKS_HOST_UNREACHABLE	=4;
   public static final int SOCKS_CONNECTION_REFUSED	=5;
   public static final int SOCKS_TTL_EXPIRE		=6;
   public static final int SOCKS_CMD_NOT_SUPPORTED	=7;
   public static final int SOCKS_ADDR_NOT_SUPPORTED	=8;

   public static final int SOCKS_NO_PROXY		=1<<16;
   public static final int SOCKS_PROXY_NO_CONNECT	=2<<16;
   public static final int SOCKS_PROXY_IO_ERROR		=3<<16;
   public static final int SOCKS_AUTH_NOT_SUPPORTED	=4<<16;
   public static final int SOCKS_AUTH_FAILURE		=5<<16;
   public static final int SOCKS_JUST_ERROR		=6<<16;

   public static final int SOCKS_DIRECT_FAILED		=7<<16;
   public static final int SOCKS_METHOD_NOTSUPPORTED	=8<<16;


   public static final int SOCKS_CMD_CONNECT 		=0x1;
   static final int SOCKS_CMD_BIND		=0x2;
   static final int SOCKS_CMD_UDP_ASSOCIATE	=0x3;

}