1 | package nu.fw.jeti.plugins.filetransfer.socks5.jsocks; |
---|
2 | |
---|
3 | import java.net.*; |
---|
4 | import java.io.*; |
---|
5 | |
---|
6 | /** |
---|
7 | * SocksSocket tryies to look very similar to normal Socket, |
---|
8 | * while allowing connections through the SOCKS4 or 5 proxy. |
---|
9 | * To use this class you will have to identify proxy you need |
---|
10 | * to use, Proxy class allows you to set default proxy, which |
---|
11 | * will be used by all Socks aware sockets. You can also create |
---|
12 | * either Socks4Proxy or Socks5Proxy, and use them by passing to the |
---|
13 | * appropriate constructors. |
---|
14 | * <P> |
---|
15 | * Using Socks package can be as easy as that: |
---|
16 | * |
---|
17 | * <pre><tt> |
---|
18 | * |
---|
19 | * import Socks.*; |
---|
20 | * .... |
---|
21 | * |
---|
22 | * try{ |
---|
23 | * //Specify SOCKS5 proxy |
---|
24 | * Proxy.setDefaultProxy("socks-proxy",1080); |
---|
25 | * |
---|
26 | * //OR you still use SOCKS4 |
---|
27 | * //Code below uses SOCKS4 proxy |
---|
28 | * //Proxy.setDefaultProxy("socks-proxy",1080,userName); |
---|
29 | * |
---|
30 | * Socket s = SocksSocket("some.host.of.mine",13); |
---|
31 | * readTimeFromSock(s); |
---|
32 | * }catch(SocksException sock_ex){ |
---|
33 | * //Usually it will turn in more or less meaningfull message |
---|
34 | * System.err.println("SocksException:"+sock_ex); |
---|
35 | * } |
---|
36 | * |
---|
37 | * </tt></pre> |
---|
38 | *<P> |
---|
39 | * However if the need exist for more control, like resolving addresses |
---|
40 | * remotely, or using some non-trivial authentication schemes, it can be done. |
---|
41 | */ |
---|
42 | |
---|
43 | public class SocksSocket extends Socket{ |
---|
44 | //Data members |
---|
45 | protected Proxy proxy; |
---|
46 | protected String localHost, remoteHost; |
---|
47 | protected InetAddress localIP, remoteIP; |
---|
48 | protected int localPort,remotePort; |
---|
49 | |
---|
50 | private Socket directSock = null; |
---|
51 | |
---|
52 | /** |
---|
53 | * Tryies to connect to given host and port |
---|
54 | * using default proxy. If no default proxy speciefied |
---|
55 | * it throws SocksException with error code SOCKS_NO_PROXY. |
---|
56 | @param host Machine to connect to. |
---|
57 | @param port Port to which to connect. |
---|
58 | * @see SocksSocket#SocksSocket(Proxy,String,int) |
---|
59 | * @see Socks5Proxy#resolveAddrLocally |
---|
60 | */ |
---|
61 | public SocksSocket(String host,int port) |
---|
62 | throws SocksException,UnknownHostException{ |
---|
63 | this(Proxy.defaultProxy,host,port); |
---|
64 | } |
---|
65 | /** |
---|
66 | * Connects to host port using given proxy server. |
---|
67 | @param p Proxy to use. |
---|
68 | @param host Machine to connect to. |
---|
69 | @param port Port to which to connect. |
---|
70 | @throws UnknownHostException |
---|
71 | If one of the following happens: |
---|
72 | <ol> |
---|
73 | |
---|
74 | <li> Proxy settings say that address should be resolved locally, but |
---|
75 | this fails. |
---|
76 | <li> Proxy settings say that the host should be contacted directly but |
---|
77 | host name can't be resolved. |
---|
78 | </ol> |
---|
79 | @throws SocksException |
---|
80 | If one of the following happens: |
---|
81 | <ul> |
---|
82 | <li> Proxy is is null. |
---|
83 | <li> Proxy settings say that the host should be contacted directly but |
---|
84 | this fails. |
---|
85 | <li> Socks Server can't be contacted. |
---|
86 | <li> Authentication fails. |
---|
87 | <li> Connection is not allowed by the SOCKS proxy. |
---|
88 | <li> SOCKS proxy can't establish the connection. |
---|
89 | <li> Any IO error occured. |
---|
90 | <li> Any protocol error occured. |
---|
91 | </ul> |
---|
92 | @throws IOexception if anything is wrong with I/O. |
---|
93 | @see Socks5Proxy#resolveAddrLocally |
---|
94 | */ |
---|
95 | public SocksSocket(Proxy p,String host,int port) |
---|
96 | throws SocksException,UnknownHostException{ |
---|
97 | |
---|
98 | |
---|
99 | if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY); |
---|
100 | //proxy=p; |
---|
101 | proxy = p.copy(); |
---|
102 | remoteHost = host; |
---|
103 | remotePort = port; |
---|
104 | if(proxy.isDirect(host)){ |
---|
105 | remoteIP = InetAddress.getByName(host); |
---|
106 | doDirect(); |
---|
107 | } |
---|
108 | else |
---|
109 | processReply(proxy.connect(host,port)); |
---|
110 | } |
---|
111 | |
---|
112 | |
---|
113 | /** |
---|
114 | * Tryies to connect to given ip and port |
---|
115 | * using default proxy. If no default proxy speciefied |
---|
116 | * it throws SocksException with error code SOCKS_NO_PROXY. |
---|
117 | @param ip Machine to connect to. |
---|
118 | @param port Port to which to connect. |
---|
119 | * @see SocksSocket#SocksSocket(Proxy,String,int) |
---|
120 | */ |
---|
121 | public SocksSocket(InetAddress ip, int port) throws SocksException{ |
---|
122 | this(Proxy.defaultProxy,ip,port); |
---|
123 | } |
---|
124 | |
---|
125 | /** |
---|
126 | Connects to given ip and port using given Proxy server. |
---|
127 | @param p Proxy to use. |
---|
128 | @param ip Machine to connect to. |
---|
129 | @param port Port to which to connect. |
---|
130 | |
---|
131 | */ |
---|
132 | public SocksSocket(Proxy p,InetAddress ip, int port) throws SocksException{ |
---|
133 | if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY); |
---|
134 | this.proxy = p.copy(); |
---|
135 | this.remoteIP = ip; |
---|
136 | this.remotePort = port; |
---|
137 | this.remoteHost = ip.getHostName(); |
---|
138 | if(proxy.isDirect(remoteIP)) |
---|
139 | doDirect(); |
---|
140 | else |
---|
141 | processReply(proxy.connect(ip,port)); |
---|
142 | } |
---|
143 | |
---|
144 | |
---|
145 | /** |
---|
146 | * These 2 constructors are used by the SocksServerSocket. |
---|
147 | * This socket simply overrides remoteHost, remotePort |
---|
148 | */ |
---|
149 | protected SocksSocket(String host,int port,Proxy proxy){ |
---|
150 | this.remotePort = port; |
---|
151 | this.proxy = proxy; |
---|
152 | this.localIP = proxy.proxySocket.getLocalAddress(); |
---|
153 | this.localPort = proxy.proxySocket.getLocalPort(); |
---|
154 | this.remoteHost = host; |
---|
155 | } |
---|
156 | protected SocksSocket(InetAddress ip,int port,Proxy proxy){ |
---|
157 | remoteIP = ip; |
---|
158 | remotePort = port; |
---|
159 | this.proxy = proxy; |
---|
160 | this.localIP = proxy.proxySocket.getLocalAddress(); |
---|
161 | this.localPort = proxy.proxySocket.getLocalPort(); |
---|
162 | remoteHost = remoteIP.getHostName(); |
---|
163 | } |
---|
164 | |
---|
165 | /** |
---|
166 | * Same as Socket |
---|
167 | */ |
---|
168 | public void close() throws IOException{ |
---|
169 | if(proxy!= null)proxy.endSession(); |
---|
170 | proxy = null; |
---|
171 | } |
---|
172 | /** |
---|
173 | * Same as Socket |
---|
174 | */ |
---|
175 | public InputStream getInputStream(){ |
---|
176 | return proxy.in; |
---|
177 | } |
---|
178 | /** |
---|
179 | * Same as Socket |
---|
180 | */ |
---|
181 | public OutputStream getOutputStream(){ |
---|
182 | return proxy.out; |
---|
183 | } |
---|
184 | /** |
---|
185 | * Same as Socket |
---|
186 | */ |
---|
187 | public int getPort(){ |
---|
188 | return remotePort; |
---|
189 | } |
---|
190 | /** |
---|
191 | * Returns remote host name, it is usefull in cases when addresses |
---|
192 | * are resolved by proxy, and we can't create InetAddress object. |
---|
193 | @return The name of the host this socket is connected to. |
---|
194 | */ |
---|
195 | public String getHost(){ |
---|
196 | return remoteHost; |
---|
197 | } |
---|
198 | /** |
---|
199 | * Get remote host as InetAddress object, might return null if |
---|
200 | * addresses are resolved by proxy, and it is not possible to resolve |
---|
201 | * it locally |
---|
202 | @return Ip address of the host this socket is connected to, or null |
---|
203 | if address was returned by the proxy as DOMAINNAME and can't be |
---|
204 | resolved locally. |
---|
205 | */ |
---|
206 | public InetAddress getInetAddress(){ |
---|
207 | if(remoteIP == null){ |
---|
208 | try{ |
---|
209 | remoteIP = InetAddress.getByName(remoteHost); |
---|
210 | }catch(UnknownHostException e){ |
---|
211 | return null; |
---|
212 | } |
---|
213 | } |
---|
214 | return remoteIP; |
---|
215 | } |
---|
216 | |
---|
217 | /** |
---|
218 | * Get the port assigned by the proxy for the socket, not |
---|
219 | * the port on locall machine as in Socket. |
---|
220 | @return Port of the socket used on the proxy server. |
---|
221 | */ |
---|
222 | public int getLocalPort(){ |
---|
223 | return localPort; |
---|
224 | } |
---|
225 | |
---|
226 | /** |
---|
227 | * Get address assigned by proxy to make a remote connection, |
---|
228 | * it might be different from the host specified for the proxy. |
---|
229 | * Can return null if socks server returned this address as hostname |
---|
230 | * and it can't be resolved locally, use getLocalHost() then. |
---|
231 | @return Address proxy is using to make a connection. |
---|
232 | */ |
---|
233 | public InetAddress getLocalAddress(){ |
---|
234 | if(localIP == null){ |
---|
235 | try{ |
---|
236 | localIP = InetAddress.getByName(localHost); |
---|
237 | }catch(UnknownHostException e){ |
---|
238 | return null; |
---|
239 | } |
---|
240 | } |
---|
241 | return localIP; |
---|
242 | } |
---|
243 | /** |
---|
244 | Get name of the host, proxy has assigned to make a remote connection |
---|
245 | for this socket. This method is usefull when proxy have returned |
---|
246 | address as hostname, and we can't resolve it on this machine. |
---|
247 | @return The name of the host proxy is using to make a connection. |
---|
248 | */ |
---|
249 | public String getLocalHost(){ |
---|
250 | return localHost; |
---|
251 | } |
---|
252 | |
---|
253 | /** |
---|
254 | Same as socket. |
---|
255 | */ |
---|
256 | public void setSoLinger(boolean on,int val) throws SocketException{ |
---|
257 | proxy.proxySocket.setSoLinger(on,val); |
---|
258 | } |
---|
259 | /** |
---|
260 | Same as socket. |
---|
261 | */ |
---|
262 | public int getSoLinger(int timeout) throws SocketException{ |
---|
263 | return proxy.proxySocket.getSoLinger(); |
---|
264 | } |
---|
265 | /** |
---|
266 | Same as socket. |
---|
267 | */ |
---|
268 | public void setSoTimeout(int timeout) throws SocketException{ |
---|
269 | proxy.proxySocket.setSoTimeout(timeout); |
---|
270 | } |
---|
271 | /** |
---|
272 | Same as socket. |
---|
273 | */ |
---|
274 | public int getSoTimeout(int timeout) throws SocketException{ |
---|
275 | return proxy.proxySocket.getSoTimeout(); |
---|
276 | } |
---|
277 | /** |
---|
278 | Same as socket. |
---|
279 | */ |
---|
280 | public void setTcpNoDelay(boolean on) throws SocketException{ |
---|
281 | proxy.proxySocket.setTcpNoDelay(on); |
---|
282 | } |
---|
283 | /** |
---|
284 | Same as socket. |
---|
285 | */ |
---|
286 | public boolean getTcpNoDelay() throws SocketException{ |
---|
287 | return proxy.proxySocket.getTcpNoDelay(); |
---|
288 | } |
---|
289 | |
---|
290 | /** |
---|
291 | Get string representation of the socket. |
---|
292 | */ |
---|
293 | public String toString(){ |
---|
294 | if(directSock!=null) return "Direct connection:"+directSock; |
---|
295 | return ("Proxy:"+proxy+";"+"addr:"+remoteHost+",port:"+remotePort |
---|
296 | +",localport:"+localPort); |
---|
297 | |
---|
298 | } |
---|
299 | |
---|
300 | //Private Methods |
---|
301 | ////////////////// |
---|
302 | |
---|
303 | private void processReply(ProxyMessage reply)throws SocksException{ |
---|
304 | localPort = reply.port; |
---|
305 | /* |
---|
306 | * If the server have assigned same host as it was contacted on |
---|
307 | * it might return an address of all zeros |
---|
308 | */ |
---|
309 | if(reply.host.equals("0.0.0.0")){ |
---|
310 | localIP = proxy.proxyIP; |
---|
311 | localHost = localIP.getHostName(); |
---|
312 | }else{ |
---|
313 | localHost = reply.host; |
---|
314 | localIP = reply.ip; |
---|
315 | } |
---|
316 | } |
---|
317 | private void doDirect()throws SocksException{ |
---|
318 | try{ |
---|
319 | //System.out.println("IP:"+remoteIP+":"+remotePort); |
---|
320 | directSock = new Socket(remoteIP,remotePort); |
---|
321 | proxy.out = directSock.getOutputStream(); |
---|
322 | proxy.in = directSock.getInputStream(); |
---|
323 | proxy.proxySocket = directSock; |
---|
324 | localIP = directSock.getLocalAddress(); |
---|
325 | localPort = directSock.getLocalPort(); |
---|
326 | }catch(IOException io_ex){ |
---|
327 | throw new SocksException(Proxy.SOCKS_DIRECT_FAILED, |
---|
328 | "Direct connect failed:"+io_ex); |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | } |
---|