mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-09-10 18:59:41 +02:00
[SMACK-226] Added proxy support via patch from Atul Aggarwal.
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@10673 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
708284ca46
commit
4c4cc77e42
7 changed files with 1875 additions and 4 deletions
|
@ -0,0 +1,398 @@
|
|||
package org.jivesoftware.smack.proxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* Socket factory for socks4 proxy
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
public class Socks4ProxySocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
private ProxyInfo proxy;
|
||||
|
||||
public Socks4ProxySocketFactory(ProxyInfo proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(host.getHostAddress(),port);
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(address.getHostAddress(),port);
|
||||
|
||||
}
|
||||
|
||||
private Socket socks4ProxifiedSocket(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = null;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
String proxy_host = proxy.getProxyAddress();
|
||||
int proxy_port = proxy.getProxyPort();
|
||||
String user = proxy.getProxyUsername();
|
||||
String passwd = proxy.getProxyPassword();
|
||||
|
||||
try
|
||||
{
|
||||
socket=new Socket(proxy_host, proxy_port);
|
||||
in=socket.getInputStream();
|
||||
out=socket.getOutputStream();
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
byte[] buf=new byte[1024];
|
||||
int index=0;
|
||||
|
||||
/*
|
||||
1) CONNECT
|
||||
|
||||
The client connects to the SOCKS server and sends a CONNECT request when
|
||||
it wants to establish a connection to an application server. The client
|
||||
includes in the request packet the IP address and the port number of the
|
||||
destination host, and userid, in the following format.
|
||||
|
||||
+----+----+----+----+----+----+----+----+----+----+....+----+
|
||||
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
|
||||
+----+----+----+----+----+----+----+----+----+----+....+----+
|
||||
# of bytes: 1 1 2 4 variable 1
|
||||
|
||||
VN is the SOCKS protocol version number and should be 4. CD is the
|
||||
SOCKS command code and should be 1 for CONNECT request. NULL is a byte
|
||||
of all zero bits.
|
||||
*/
|
||||
|
||||
index=0;
|
||||
buf[index++]=4;
|
||||
buf[index++]=1;
|
||||
|
||||
buf[index++]=(byte)(port>>>8);
|
||||
buf[index++]=(byte)(port&0xff);
|
||||
|
||||
try
|
||||
{
|
||||
InetAddress addr=InetAddress.getByName(host);
|
||||
byte[] byteAddress = addr.getAddress();
|
||||
for (int i = 0; i < byteAddress.length; i++)
|
||||
{
|
||||
buf[index++]=byteAddress[i];
|
||||
}
|
||||
}
|
||||
catch(UnknownHostException uhe)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
uhe.toString(), uhe);
|
||||
}
|
||||
|
||||
if(user!=null)
|
||||
{
|
||||
System.arraycopy(user.getBytes(), 0, buf, index, user.length());
|
||||
index+=user.length();
|
||||
}
|
||||
buf[index++]=0;
|
||||
out.write(buf, 0, index);
|
||||
|
||||
/*
|
||||
The SOCKS server checks to see whether such a request should be granted
|
||||
based on any combination of source IP address, destination IP address,
|
||||
destination port number, the userid, and information it may obtain by
|
||||
consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
|
||||
server makes a connection to the specified port of the destination host.
|
||||
A reply packet is sent to the client when this connection is established,
|
||||
or when the request is rejected or the operation fails.
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| VN | CD | DSTPORT | DSTIP |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
# of bytes: 1 1 2 4
|
||||
|
||||
VN is the version of the reply code and should be 0. CD is the result
|
||||
code with one of the following values:
|
||||
|
||||
90: request granted
|
||||
91: request rejected or failed
|
||||
92: request rejected becasue SOCKS server cannot connect to
|
||||
identd on the client
|
||||
93: request rejected because the client program and identd
|
||||
report different user-ids
|
||||
|
||||
The remaining fields are ignored.
|
||||
*/
|
||||
|
||||
int len=6;
|
||||
int s=0;
|
||||
while(s<len)
|
||||
{
|
||||
int i=in.read(buf, s, len-s);
|
||||
if(i<=0)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
"stream is closed");
|
||||
}
|
||||
s+=i;
|
||||
}
|
||||
if(buf[0]!=0)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
"server returns VN "+buf[0]);
|
||||
}
|
||||
if(buf[1]!=90)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
}
|
||||
String message="ProxySOCKS4: server returns CD "+buf[1];
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,message);
|
||||
}
|
||||
byte[] temp = new byte[2];
|
||||
in.read(temp, 0, 2);
|
||||
return socket;
|
||||
}
|
||||
catch(RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(socket!=null)socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
}
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.jivesoftware.smack.proxy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* Socket factory for socks4 proxy
|
||||
*
|
||||
* @author Atul Aggarwal
|
||||
*/
|
||||
public class Socks4ProxySocketFactory
|
||||
extends SocketFactory
|
||||
{
|
||||
private ProxyInfo proxy;
|
||||
|
||||
public Socks4ProxySocketFactory(ProxyInfo proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Socket createSocket(String host, int port)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
|
||||
}
|
||||
|
||||
public Socket createSocket(String host ,int port, InetAddress localHost,
|
||||
int localPort)
|
||||
throws IOException, UnknownHostException
|
||||
{
|
||||
return socks4ProxifiedSocket(host,port);
|
||||
}
|
||||
|
||||
public Socket createSocket(InetAddress host, int port)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(host.getHostAddress(),port);
|
||||
}
|
||||
|
||||
public Socket createSocket( InetAddress address, int port,
|
||||
InetAddress localAddress, int localPort)
|
||||
throws IOException
|
||||
{
|
||||
return socks4ProxifiedSocket(address.getHostAddress(),port);
|
||||
|
||||
}
|
||||
|
||||
private Socket socks4ProxifiedSocket(String host, int port)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = null;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
String proxy_host = proxy.getProxyAddress();
|
||||
int proxy_port = proxy.getProxyPort();
|
||||
String user = proxy.getProxyUsername();
|
||||
String passwd = proxy.getProxyPassword();
|
||||
|
||||
try
|
||||
{
|
||||
socket=new Socket(proxy_host, proxy_port);
|
||||
in=socket.getInputStream();
|
||||
out=socket.getOutputStream();
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
byte[] buf=new byte[1024];
|
||||
int index=0;
|
||||
|
||||
/*
|
||||
1) CONNECT
|
||||
|
||||
The client connects to the SOCKS server and sends a CONNECT request when
|
||||
it wants to establish a connection to an application server. The client
|
||||
includes in the request packet the IP address and the port number of the
|
||||
destination host, and userid, in the following format.
|
||||
|
||||
+----+----+----+----+----+----+----+----+----+----+....+----+
|
||||
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
|
||||
+----+----+----+----+----+----+----+----+----+----+....+----+
|
||||
# of bytes: 1 1 2 4 variable 1
|
||||
|
||||
VN is the SOCKS protocol version number and should be 4. CD is the
|
||||
SOCKS command code and should be 1 for CONNECT request. NULL is a byte
|
||||
of all zero bits.
|
||||
*/
|
||||
|
||||
index=0;
|
||||
buf[index++]=4;
|
||||
buf[index++]=1;
|
||||
|
||||
buf[index++]=(byte)(port>>>8);
|
||||
buf[index++]=(byte)(port&0xff);
|
||||
|
||||
try
|
||||
{
|
||||
InetAddress addr=InetAddress.getByName(host);
|
||||
byte[] byteAddress = addr.getAddress();
|
||||
for (int i = 0; i < byteAddress.length; i++)
|
||||
{
|
||||
buf[index++]=byteAddress[i];
|
||||
}
|
||||
}
|
||||
catch(UnknownHostException uhe)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
uhe.toString(), uhe);
|
||||
}
|
||||
|
||||
if(user!=null)
|
||||
{
|
||||
System.arraycopy(user.getBytes(), 0, buf, index, user.length());
|
||||
index+=user.length();
|
||||
}
|
||||
buf[index++]=0;
|
||||
out.write(buf, 0, index);
|
||||
|
||||
/*
|
||||
The SOCKS server checks to see whether such a request should be granted
|
||||
based on any combination of source IP address, destination IP address,
|
||||
destination port number, the userid, and information it may obtain by
|
||||
consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
|
||||
server makes a connection to the specified port of the destination host.
|
||||
A reply packet is sent to the client when this connection is established,
|
||||
or when the request is rejected or the operation fails.
|
||||
|
||||
+----+----+----+----+----+----+----+----+
|
||||
| VN | CD | DSTPORT | DSTIP |
|
||||
+----+----+----+----+----+----+----+----+
|
||||
# of bytes: 1 1 2 4
|
||||
|
||||
VN is the version of the reply code and should be 0. CD is the result
|
||||
code with one of the following values:
|
||||
|
||||
90: request granted
|
||||
91: request rejected or failed
|
||||
92: request rejected becasue SOCKS server cannot connect to
|
||||
identd on the client
|
||||
93: request rejected because the client program and identd
|
||||
report different user-ids
|
||||
|
||||
The remaining fields are ignored.
|
||||
*/
|
||||
|
||||
int len=6;
|
||||
int s=0;
|
||||
while(s<len)
|
||||
{
|
||||
int i=in.read(buf, s, len-s);
|
||||
if(i<=0)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
"stream is closed");
|
||||
}
|
||||
s+=i;
|
||||
}
|
||||
if(buf[0]!=0)
|
||||
{
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,
|
||||
"server returns VN "+buf[0]);
|
||||
}
|
||||
if(buf[1]!=90)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
}
|
||||
String message="ProxySOCKS4: server returns CD "+buf[1];
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4,message);
|
||||
}
|
||||
byte[] temp = new byte[2];
|
||||
in.read(temp, 0, 2);
|
||||
return socket;
|
||||
}
|
||||
catch(RuntimeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(socket!=null)socket.close();
|
||||
}
|
||||
catch(Exception eee)
|
||||
{
|
||||
}
|
||||
throw new ProxyException(ProxyInfo.ProxyType.SOCKS4, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue