SocksSocketImplpublic class SocksSocketImpl extends PlainSocketImpl implements SocksConstsSOCKS (V4 & V5) TCP socket implementation (RFC 1928).
This is a subclass of PlainSocketImpl.
Note this class should NOT be public. |
Fields Summary |
---|
private String | server | private int | port | private InetSocketAddress | external_address | private boolean | useV4 | private Socket | cmdsock | private InputStream | cmdIn | private OutputStream | cmdOut |
Constructors Summary |
---|
SocksSocketImpl()
// Nothing needed
| SocksSocketImpl(String server, int port)
this.server = server;
this.port = (port == -1 ? DEFAULT_PORT : port);
| SocksSocketImpl(Proxy proxy)
SocketAddress a = proxy.address();
if (a instanceof InetSocketAddress) {
InetSocketAddress ad = (InetSocketAddress) a;
// Use getHostString() to avoid reverse lookups
server = ad.getHostString();
port = ad.getPort();
}
|
Methods Summary |
---|
protected void | acceptFrom(java.net.SocketImpl s, java.net.InetSocketAddress saddr)Accepts a connection from a specific host.
if (cmdsock == null) {
// Not a Socks ServerSocket.
return;
}
InputStream in = cmdIn;
// Sends the "SOCKS BIND" request.
socksBind(saddr);
in.read();
int i = in.read();
in.read();
SocketException ex = null;
int nport;
byte[] addr;
InetSocketAddress real_end = null;
switch (i) {
case REQUEST_OK:
// success!
i = in.read();
switch(i) {
case IPV4:
addr = new byte[4];
readSocksReply(in, addr);
nport = in.read() << 8;
nport += in.read();
real_end =
new InetSocketAddress(new Inet4Address("", addr) , nport);
break;
case DOMAIN_NAME:
int len = in.read();
addr = new byte[len];
readSocksReply(in, addr);
nport = in.read() << 8;
nport += in.read();
real_end = new InetSocketAddress(new String(addr), nport);
break;
case IPV6:
addr = new byte[16];
readSocksReply(in, addr);
nport = in.read() << 8;
nport += in.read();
real_end =
new InetSocketAddress(new Inet6Address("", addr), nport);
break;
}
break;
case GENERAL_FAILURE:
ex = new SocketException("SOCKS server general failure");
break;
case NOT_ALLOWED:
ex = new SocketException("SOCKS: Accept not allowed by ruleset");
break;
case NET_UNREACHABLE:
ex = new SocketException("SOCKS: Network unreachable");
break;
case HOST_UNREACHABLE:
ex = new SocketException("SOCKS: Host unreachable");
break;
case CONN_REFUSED:
ex = new SocketException("SOCKS: Connection refused");
break;
case TTL_EXPIRED:
ex = new SocketException("SOCKS: TTL expired");
break;
case CMD_NOT_SUPPORTED:
ex = new SocketException("SOCKS: Command not supported");
break;
case ADDR_TYPE_NOT_SUP:
ex = new SocketException("SOCKS: address type not supported");
break;
}
if (ex != null) {
cmdIn.close();
cmdOut.close();
cmdsock.close();
cmdsock = null;
throw ex;
}
/**
* This is where we have to do some fancy stuff.
* The datastream from the socket "accepted" by the proxy will
* come through the cmdSocket. So we have to swap the socketImpls
*/
if (s instanceof SocksSocketImpl) {
((SocksSocketImpl)s).external_address = real_end;
}
if (s instanceof PlainSocketImpl) {
((PlainSocketImpl)s).setInputStream((SocketInputStream) in);
}
s.fd = cmdsock.getImpl().fd;
s.address = cmdsock.getImpl().address;
s.port = cmdsock.getImpl().port;
s.localport = cmdsock.getImpl().localport;
// Need to do that so that the socket won't be closed
// when the ServerSocket is closed by the user.
// It kinds of detaches the Socket because it is now
// used elsewhere.
cmdsock = null;
| private boolean | authenticate(byte method, java.io.InputStream in, java.io.BufferedOutputStream out)Provides the authentication machanism required by the proxy.
byte[] data = null;
int i;
// No Authentication required. We're done then!
if (method == NO_AUTH)
return true;
/**
* User/Password authentication. Try, in that order :
* - The application provided Authenticator, if any
* - The user preferences java.net.socks.username &
* java.net.socks.password
* - the user.name & no password (backward compatibility behavior).
*/
if (method == USER_PASSW) {
String userName;
String password = null;
final InetAddress addr = InetAddress.getByName(server);
PasswordAuthentication pw = (PasswordAuthentication)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return Authenticator.requestPasswordAuthentication(
server, addr, port, "SOCKS5", "SOCKS authentication", null);
}
});
if (pw != null) {
userName = pw.getUserName();
password = new String(pw.getPassword());
} else {
final Preferences prefs = Preferences.userRoot().node("/java/net/socks");
try {
userName =
(String) AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction() {
public Object run() throws IOException {
return prefs.get("username", null);
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (IOException) pae.getException();
}
if (userName != null) {
try {
password =
(String) AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction() {
public Object run() throws IOException {
return prefs.get("password", null);
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (IOException) pae.getException();
}
} else {
userName =
(String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.name"));
}
}
if (userName == null)
return false;
out.write(1);
out.write(userName.length());
try {
out.write(userName.getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
if (password != null) {
out.write(password.length());
try {
out.write(password.getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
} else
out.write(0);
out.flush();
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2 || data[1] != 0) {
/* RFC 1929 specifies that the connection MUST be closed if
authentication fails */
out.close();
in.close();
return false;
}
/* Authentication succeeded */
return true;
}
/**
* GSSAPI authentication mechanism.
* Unfortunately the RFC seems out of sync with the Reference
* implementation. I'll leave this in for future completion.
*/
// if (method == GSSAPI) {
// try {
// GSSManager manager = GSSManager.getInstance();
// GSSName name = manager.createName("SERVICE:socks@"+server,
// null);
// GSSContext context = manager.createContext(name, null, null,
// GSSContext.DEFAULT_LIFETIME);
// context.requestMutualAuth(true);
// context.requestReplayDet(true);
// context.requestSequenceDet(true);
// context.requestCredDeleg(true);
// byte []inToken = new byte[0];
// while (!context.isEstablished()) {
// byte[] outToken
// = context.initSecContext(inToken, 0, inToken.length);
// // send the output token if generated
// if (outToken != null) {
// out.write(1);
// out.write(1);
// out.writeShort(outToken.length);
// out.write(outToken);
// out.flush();
// data = new byte[2];
// i = readSocksReply(in, data);
// if (i != 2 || data[1] == 0xff) {
// in.close();
// out.close();
// return false;
// }
// i = readSocksReply(in, data);
// int len = 0;
// len = ((int)data[0] & 0xff) << 8;
// len += data[1];
// data = new byte[len];
// i = readSocksReply(in, data);
// if (i == len)
// return true;
// in.close();
// out.close();
// }
// }
// } catch (GSSException e) {
// /* RFC 1961 states that if Context initialisation fails the connection
// MUST be closed */
// e.printStackTrace();
// in.close();
// out.close();
// }
// }
return false;
| private void | bindV4(java.io.InputStream in, java.io.OutputStream out, java.net.InetAddress baddr, int lport)
if (!(baddr instanceof Inet4Address)) {
throw new SocketException("SOCKS V4 requires IPv4 only addresses");
}
super.bind(baddr, lport);
byte[] addr1 = baddr.getAddress();
/* Test for AnyLocal */
InetAddress naddr = baddr;
if (naddr.isAnyLocalAddress()) {
naddr = cmdsock.getLocalAddress();
addr1 = naddr.getAddress();
}
out.write(PROTO_VERS4);
out.write(BIND);
out.write((super.getLocalPort() >> 8) & 0xff);
out.write((super.getLocalPort() >> 0) & 0xff);
out.write(addr1);
String userName = (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.name"));
try {
out.write(userName.getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
out.write(0);
out.flush();
byte[] data = new byte[8];
int n = readSocksReply(in, data);
if (n != 8)
throw new SocketException("Reply from SOCKS server has bad length: " + n);
if (data[0] != 0 && data[0] != 4)
throw new SocketException("Reply from SOCKS server has bad version");
SocketException ex = null;
switch (data[1]) {
case 90:
// Success!
external_address = new InetSocketAddress(baddr, lport);
break;
case 91:
ex = new SocketException("SOCKS request rejected");
break;
case 92:
ex = new SocketException("SOCKS server couldn't reach destination");
break;
case 93:
ex = new SocketException("SOCKS authentication failed");
break;
default:
ex = new SocketException("Reply from SOCKS server contains bad status");
break;
}
if (ex != null) {
in.close();
out.close();
throw ex;
}
| protected void | close()
if (cmdsock != null)
cmdsock.close();
cmdsock = null;
super.close();
| protected void | connect(java.net.SocketAddress endpoint, int timeout)Connects the Socks Socket to the specified endpoint. It will first
connect to the SOCKS proxy and negotiate the access. If the proxy
grants the connections, then the connect is successful and all
further traffic will go to the "real" endpoint.
SecurityManager security = System.getSecurityManager();
if (endpoint == null || !(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint = (InetSocketAddress) endpoint;
if (security != null) {
if (epoint.isUnresolved())
security.checkConnect(epoint.getHostName(),
epoint.getPort());
else
security.checkConnect(epoint.getAddress().getHostAddress(),
epoint.getPort());
}
if (server == null) {
// This is the general case
// server is not null only when the socket was created with a
// specified proxy in which case it does bypass the ProxySelector
ProxySelector sel = (ProxySelector)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return ProxySelector.getDefault();
}
});
if (sel == null) {
/*
* No default proxySelector --> direct connection
*/
super.connect(epoint, timeout);
return;
}
URI uri = null;
// Use getHostString() to avoid reverse lookups
String host = epoint.getHostString();
// IPv6 litteral?
if (epoint.getAddress() instanceof Inet6Address &&
(!host.startsWith("[")) && (host.indexOf(":") >= 0)) {
host = "[" + host + "]";
}
try {
uri = new URI("socket://" + ParseUtil.encodePath(host) + ":"+ epoint.getPort());
} catch (URISyntaxException e) {
// This shouldn't happen
assert false : e;
}
Proxy p = null;
IOException savedExc = null;
java.util.Iterator<Proxy> iProxy = null;
iProxy = sel.select(uri).iterator();
if (iProxy == null || !(iProxy.hasNext())) {
super.connect(epoint, timeout);
return;
}
while (iProxy.hasNext()) {
p = iProxy.next();
if (p == null || p == Proxy.NO_PROXY) {
super.connect(epoint, timeout);
return;
}
if (p.type() != Proxy.Type.SOCKS)
throw new SocketException("Unknown proxy type : " + p.type());
if (!(p.address() instanceof InetSocketAddress))
throw new SocketException("Unknow address type for proxy: " + p);
// Use getHostString() to avoid reverse lookups
server = ((InetSocketAddress) p.address()).getHostString();
port = ((InetSocketAddress) p.address()).getPort();
// Connects to the SOCKS server
try {
privilegedConnect(server, port, timeout);
// Worked, let's get outta here
break;
} catch (IOException e) {
// Ooops, let's notify the ProxySelector
sel.connectFailed(uri,p.address(),e);
server = null;
port = -1;
savedExc = e;
// Will continue the while loop and try the next proxy
}
}
/*
* If server is still null at this point, none of the proxy
* worked
*/
if (server == null) {
throw new SocketException("Can't connect to SOCKS proxy:"
+ savedExc.getMessage());
}
} else {
// Connects to the SOCKS server
try {
privilegedConnect(server, port, timeout);
} catch (IOException e) {
throw new SocketException(e.getMessage());
}
}
// cmdIn & cmdOut were intialized during the privilegedConnect() call
BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
InputStream in = cmdIn;
if (useV4) {
// SOCKS Protocol version 4 doesn't know how to deal with
// DOMAIN type of addresses (unresolved addresses here)
if (epoint.isUnresolved())
throw new UnknownHostException(epoint.toString());
connectV4(in, out, epoint);
return;
}
// This is SOCKS V5
out.write(PROTO_VERS);
out.write(2);
out.write(NO_AUTH);
out.write(USER_PASSW);
out.flush();
byte[] data = new byte[2];
int i = readSocksReply(in, data);
if (i != 2 || ((int)data[0]) != PROTO_VERS) {
// Maybe it's not a V5 sever after all
// Let's try V4 before we give up
// SOCKS Protocol version 4 doesn't know how to deal with
// DOMAIN type of addresses (unresolved addresses here)
if (epoint.isUnresolved())
throw new UnknownHostException(epoint.toString());
connectV4(in, out, epoint);
return;
}
if (((int)data[1]) == NO_METHODS)
throw new SocketException("SOCKS : No acceptable methods");
if (!authenticate(data[1], in, out)) {
throw new SocketException("SOCKS : authentication failed");
}
out.write(PROTO_VERS);
out.write(CONNECT);
out.write(0);
/* Test for IPV4/IPV6/Unresolved */
if (epoint.isUnresolved()) {
out.write(DOMAIN_NAME);
out.write(epoint.getHostName().length());
try {
out.write(epoint.getHostName().getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
out.write((epoint.getPort() >> 8) & 0xff);
out.write((epoint.getPort() >> 0) & 0xff);
} else if (epoint.getAddress() instanceof Inet6Address) {
out.write(IPV6);
out.write(epoint.getAddress().getAddress());
out.write((epoint.getPort() >> 8) & 0xff);
out.write((epoint.getPort() >> 0) & 0xff);
} else {
out.write(IPV4);
out.write(epoint.getAddress().getAddress());
out.write((epoint.getPort() >> 8) & 0xff);
out.write((epoint.getPort() >> 0) & 0xff);
}
out.flush();
data = new byte[4];
i = readSocksReply(in, data);
if (i != 4)
throw new SocketException("Reply from SOCKS server has bad length");
SocketException ex = null;
int nport, len;
byte[] addr;
switch (data[1]) {
case REQUEST_OK:
// success!
switch(data[3]) {
case IPV4:
addr = new byte[4];
i = readSocksReply(in, addr);
if (i != 4)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
break;
case DOMAIN_NAME:
len = data[1];
byte[] host = new byte[len];
i = readSocksReply(in, host);
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
break;
case IPV6:
len = data[1];
addr = new byte[len];
i = readSocksReply(in, addr);
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
break;
default:
ex = new SocketException("Reply from SOCKS server contains wrong code");
break;
}
break;
case GENERAL_FAILURE:
ex = new SocketException("SOCKS server general failure");
break;
case NOT_ALLOWED:
ex = new SocketException("SOCKS: Connection not allowed by ruleset");
break;
case NET_UNREACHABLE:
ex = new SocketException("SOCKS: Network unreachable");
break;
case HOST_UNREACHABLE:
ex = new SocketException("SOCKS: Host unreachable");
break;
case CONN_REFUSED:
ex = new SocketException("SOCKS: Connection refused");
break;
case TTL_EXPIRED:
ex = new SocketException("SOCKS: TTL expired");
break;
case CMD_NOT_SUPPORTED:
ex = new SocketException("SOCKS: Command not supported");
break;
case ADDR_TYPE_NOT_SUP:
ex = new SocketException("SOCKS: address type not supported");
break;
}
if (ex != null) {
in.close();
out.close();
throw ex;
}
external_address = epoint;
| private void | connectV4(java.io.InputStream in, java.io.OutputStream out, java.net.InetSocketAddress endpoint)
if (!(endpoint.getAddress() instanceof Inet4Address)) {
throw new SocketException("SOCKS V4 requires IPv4 only addresses");
}
out.write(PROTO_VERS4);
out.write(CONNECT);
out.write((endpoint.getPort() >> 8) & 0xff);
out.write((endpoint.getPort() >> 0) & 0xff);
out.write(endpoint.getAddress().getAddress());
String userName = (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("user.name"));
try {
out.write(userName.getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
out.write(0);
out.flush();
byte[] data = new byte[8];
int n = readSocksReply(in, data);
if (n != 8)
throw new SocketException("Reply from SOCKS server has bad length: " + n);
if (data[0] != 0 && data[0] != 4)
throw new SocketException("Reply from SOCKS server has bad version");
SocketException ex = null;
switch (data[1]) {
case 90:
// Success!
external_address = endpoint;
break;
case 91:
ex = new SocketException("SOCKS request rejected");
break;
case 92:
ex = new SocketException("SOCKS server couldn't reach destination");
break;
case 93:
ex = new SocketException("SOCKS authentication failed");
break;
default:
ex = new SocketException("Reply from SOCKS server contains bad status");
break;
}
if (ex != null) {
in.close();
out.close();
throw ex;
}
| protected java.net.InetAddress | getInetAddress()Returns the value of this socket's address field.
if (external_address != null)
return external_address.getAddress();
else
return super.getInetAddress();
| protected int | getLocalPort()
if (socket != null)
return super.getLocalPort();
if (external_address != null)
return external_address.getPort();
else
return super.getLocalPort();
| protected int | getPort()Returns the value of this socket's port field.
if (external_address != null)
return external_address.getPort();
else
return super.getPort();
| private synchronized void | privilegedConnect(java.lang.String host, int port, int timeout)
try {
AccessController.doPrivileged(
new java.security.PrivilegedExceptionAction() {
public Object run() throws IOException {
superConnectServer(host, port, timeout);
cmdIn = getInputStream();
cmdOut = getOutputStream();
return null;
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (IOException) pae.getException();
}
| private int | readSocksReply(java.io.InputStream in, byte[] data)
int len = data.length;
int received = 0;
for (int attempts = 0; received < len && attempts < 3; attempts++) {
int count = in.read(data, received, len - received);
if (count < 0)
throw new SocketException("Malformed reply from SOCKS server");
received += count;
}
return received;
| void | setV4()
useV4 = true;
| protected synchronized void | socksBind(java.net.InetSocketAddress saddr)Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind
means "accept incoming connection from", so the SocketAddress is the
the one of the host we do accept connection from.
if (socket != null) {
// this is a client socket, not a server socket, don't
// call the SOCKS proxy for a bind!
return;
}
// Connects to the SOCKS server
if (server == null) {
// This is the general case
// server is not null only when the socket was created with a
// specified proxy in which case it does bypass the ProxySelector
ProxySelector sel = (ProxySelector)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
return ProxySelector.getDefault();
}
});
if (sel == null) {
/*
* No default proxySelector --> direct connection
*/
return;
}
URI uri = null;
// Use getHostString() to avoid reverse lookups
String host = saddr.getHostString();
// IPv6 litteral?
if (saddr.getAddress() instanceof Inet6Address &&
(!host.startsWith("[")) && (host.indexOf(":") >= 0)) {
host = "[" + host + "]";
}
try {
uri = new URI("serversocket://" + ParseUtil.encodePath(host) + ":"+ saddr.getPort());
} catch (URISyntaxException e) {
// This shouldn't happen
assert false : e;
}
Proxy p = null;
Exception savedExc = null;
java.util.Iterator<Proxy> iProxy = null;
iProxy = sel.select(uri).iterator();
if (iProxy == null || !(iProxy.hasNext())) {
return;
}
while (iProxy.hasNext()) {
p = iProxy.next();
if (p == null || p == Proxy.NO_PROXY) {
return;
}
if (p.type() != Proxy.Type.SOCKS)
throw new SocketException("Unknown proxy type : " + p.type());
if (!(p.address() instanceof InetSocketAddress))
throw new SocketException("Unknow address type for proxy: " + p);
// Use getHostString() to avoid reverse lookups
server = ((InetSocketAddress) p.address()).getHostString();
port = ((InetSocketAddress) p.address()).getPort();
// Connects to the SOCKS server
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
cmdsock = new Socket(new PlainSocketImpl());
cmdsock.connect(new InetSocketAddress(server, port));
cmdIn = cmdsock.getInputStream();
cmdOut = cmdsock.getOutputStream();
return null;
}
});
} catch (Exception e) {
// Ooops, let's notify the ProxySelector
sel.connectFailed(uri,p.address(),new SocketException(e.getMessage()));
server = null;
port = -1;
cmdsock = null;
savedExc = e;
// Will continue the while loop and try the next proxy
}
}
/*
* If server is still null at this point, none of the proxy
* worked
*/
if (server == null || cmdsock == null) {
throw new SocketException("Can't connect to SOCKS proxy:"
+ savedExc.getMessage());
}
} else {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
cmdsock = new Socket(new PlainSocketImpl());
cmdsock.connect(new InetSocketAddress(server, port));
cmdIn = cmdsock.getInputStream();
cmdOut = cmdsock.getOutputStream();
return null;
}
});
} catch (Exception e) {
throw new SocketException(e.getMessage());
}
}
BufferedOutputStream out = new BufferedOutputStream(cmdOut, 512);
InputStream in = cmdIn;
if (useV4) {
bindV4(in, out, saddr.getAddress(), saddr.getPort());
return;
}
out.write(PROTO_VERS);
out.write(2);
out.write(NO_AUTH);
out.write(USER_PASSW);
out.flush();
byte[] data = new byte[2];
int i = readSocksReply(in, data);
if (i != 2 || ((int)data[0]) != PROTO_VERS) {
// Maybe it's not a V5 sever after all
// Let's try V4 before we give up
bindV4(in, out, saddr.getAddress(), saddr.getPort());
return;
}
if (((int)data[1]) == NO_METHODS)
throw new SocketException("SOCKS : No acceptable methods");
if (!authenticate(data[1], in, out)) {
throw new SocketException("SOCKS : authentication failed");
}
// We're OK. Let's issue the BIND command.
out.write(PROTO_VERS);
out.write(BIND);
out.write(0);
int lport = saddr.getPort();
if (saddr.isUnresolved()) {
out.write(DOMAIN_NAME);
out.write(saddr.getHostName().length());
try {
out.write(saddr.getHostName().getBytes("ISO-8859-1"));
} catch (java.io.UnsupportedEncodingException uee) {
assert false;
}
out.write((lport >> 8) & 0xff);
out.write((lport >> 0) & 0xff);
} else if (saddr.getAddress() instanceof Inet4Address) {
byte[] addr1 = saddr.getAddress().getAddress();
out.write(IPV4);
out.write(addr1);
out.write((lport >> 8) & 0xff);
out.write((lport >> 0) & 0xff);
out.flush();
} else if (saddr.getAddress() instanceof Inet6Address) {
byte[] addr1 = saddr.getAddress().getAddress();
out.write(IPV6);
out.write(addr1);
out.write((lport >> 8) & 0xff);
out.write((lport >> 0) & 0xff);
out.flush();
} else {
cmdsock.close();
throw new SocketException("unsupported address type : " + saddr);
}
data = new byte[4];
i = readSocksReply(in, data);
SocketException ex = null;
int len, nport;
byte[] addr;
switch (data[1]) {
case REQUEST_OK:
// success!
InetSocketAddress real_end = null;
switch(data[3]) {
case IPV4:
addr = new byte[4];
i = readSocksReply(in, addr);
if (i != 4)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
external_address =
new InetSocketAddress(new Inet4Address("", addr) , nport);
break;
case DOMAIN_NAME:
len = data[1];
byte[] host = new byte[len];
i = readSocksReply(in, host);
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
external_address = new InetSocketAddress(new String(host), nport);
break;
case IPV6:
len = data[1];
addr = new byte[len];
i = readSocksReply(in, addr);
if (i != len)
throw new SocketException("Reply from SOCKS server badly formatted");
data = new byte[2];
i = readSocksReply(in, data);
if (i != 2)
throw new SocketException("Reply from SOCKS server badly formatted");
nport = ((int)data[0] & 0xff) << 8;
nport += ((int)data[1] & 0xff);
external_address =
new InetSocketAddress(new Inet6Address("", addr), nport);
break;
}
break;
case GENERAL_FAILURE:
ex = new SocketException("SOCKS server general failure");
break;
case NOT_ALLOWED:
ex = new SocketException("SOCKS: Bind not allowed by ruleset");
break;
case NET_UNREACHABLE:
ex = new SocketException("SOCKS: Network unreachable");
break;
case HOST_UNREACHABLE:
ex = new SocketException("SOCKS: Host unreachable");
break;
case CONN_REFUSED:
ex = new SocketException("SOCKS: Connection refused");
break;
case TTL_EXPIRED:
ex = new SocketException("SOCKS: TTL expired");
break;
case CMD_NOT_SUPPORTED:
ex = new SocketException("SOCKS: Command not supported");
break;
case ADDR_TYPE_NOT_SUP:
ex = new SocketException("SOCKS: address type not supported");
break;
}
if (ex != null) {
in.close();
out.close();
cmdsock.close();
cmdsock = null;
throw ex;
}
cmdIn = in;
cmdOut = out;
| private void | superConnectServer(java.lang.String host, int port, int timeout)
super.connect(new InetSocketAddress(host, port), timeout);
|
|