/** Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.net;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.BufferedOutputStream;import java.security.AccessController;import java.security.PrivilegedAction;import java.security.PrivilegedExceptionAction;import jdk.internal.util.StaticProperty;import sun.net.SocksProxy;import sun.net.spi.DefaultProxySelector;import sun.net.www.ParseUtil;/* import org.ietf.jgss.*; *//*** SOCKS (V4 & V5) TCP socket implementation (RFC 1928).* This is a subclass of PlainSocketImpl.* Note this class should <b>NOT</b> be public.*/class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {private String server = null;private int serverPort = DEFAULT_PORT;private InetSocketAddress external_address;private boolean useV4 = false;private Socket cmdsock = null;private InputStream cmdIn = null;private OutputStream cmdOut = null;/* true if the Proxy has been set programatically */private boolean applicationSetProxy; /* false */SocksSocketImpl() {// Nothing needed}SocksSocketImpl(String server, int port) {this.server = server;this.serverPort = (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 lookupsserver = ad.getHostString();serverPort = ad.getPort();}useV4 = useV4(proxy);}void setV4() {useV4 = true;}private static boolean useV4(Proxy proxy) {if (proxy instanceof SocksProxy&& ((SocksProxy)proxy).protocolVersion() == 4) {return true;}return DefaultProxySelector.socksProxyVersion() == 4;}private synchronized void privilegedConnect(final String host,final int port,final int timeout)throws IOException{try {AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<>() {public Void run() throws IOException {superConnectServer(host, port, timeout);cmdIn = getInputStream();cmdOut = getOutputStream();return null;}});} catch (java.security.PrivilegedActionException pae) {throw (IOException) pae.getException();}}private void superConnectServer(String host, int port,int timeout) throws IOException {super.connect(new InetSocketAddress(host, port), timeout);}private static int remainingMillis(long deadlineMillis) throws IOException {if (deadlineMillis == 0L)return 0;final long remaining = deadlineMillis - System.currentTimeMillis();if (remaining > 0)return (int) remaining;throw new SocketTimeoutException();}private int readSocksReply(InputStream in, byte[] data) throws IOException {return readSocksReply(in, data, 0L);}private int readSocksReply(InputStream in, byte[] data, long deadlineMillis) throws IOException {int len = data.length;int received = 0;while (received < len) {int count;try {count = ((SocketInputStream)in).read(data, received, len - received, remainingMillis(deadlineMillis));} catch (SocketTimeoutException e) {throw new SocketTimeoutException("Connect timed out");}if (count < 0)throw new SocketException("Malformed reply from SOCKS server");received += count;}return received;}/*** Provides the authentication machanism required by the proxy.*/private boolean authenticate(byte method, InputStream in,BufferedOutputStream out) throws IOException {return authenticate(method, in, out, 0L);}private boolean authenticate(byte method, InputStream in,BufferedOutputStream out,long deadlineMillis) throws IOException {// 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.name & no password (backward compatibility behavior).*/if (method == USER_PASSW) {String userName;String password = null;final InetAddress addr = InetAddress.getByName(server);PasswordAuthentication pw =java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<>() {public PasswordAuthentication run() {return Authenticator.requestPasswordAuthentication(server, addr, serverPort, "SOCKS5", "SOCKS authentication", null);}});if (pw != null) {userName = pw.getUserName();password = new String(pw.getPassword());} else {userName = StaticProperty.userName();}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;}} elseout.write(0);out.flush();byte[] data = new byte[2];int i = readSocksReply(in, data, deadlineMillis);if (i != 2 || data[1] != 0) {/* RFC 1929 specifies that the connection MUST be closed ifauthentication 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, deadlineMillis);// if (i != 2 || data[1] == 0xff) {// in.close();// out.close();// return false;// }// i = readSocksReply(in, data, deadlineMillis);// int len = 0;// len = ((int)data[0] & 0xff) << 8;// len += data[1];// data = new byte[len];// i = readSocksReply(in, data, deadlineMillis);// 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 connectV4(InputStream in, OutputStream out,InetSocketAddress endpoint,long deadlineMillis) throws IOException {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 = getUserName();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, deadlineMillis);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;}}/*** 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.** @param endpoint the {@code SocketAddress} to connect to.* @param timeout the timeout value in milliseconds* @throws IOException if the connection can't be established.* @throws SecurityException if there is a security manager and it* doesn't allow the connection* @throws IllegalArgumentException if endpoint is null or a* SocketAddress subclass not supported by this socket*/@Overrideprotected void connect(SocketAddress endpoint, int timeout) throws IOException {final long deadlineMillis;if (timeout == 0) {deadlineMillis = 0L;} else {long finish = System.currentTimeMillis() + timeout;deadlineMillis = finish < 0 ? Long.MAX_VALUE : finish;}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());elsesecurity.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 ProxySelectorProxySelector sel = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<>() {public ProxySelector run() {return ProxySelector.getDefault();}});if (sel == null) {/** No default proxySelector --> direct connection*/super.connect(epoint, remainingMillis(deadlineMillis));return;}URI uri;// Use getHostString() to avoid reverse lookupsString 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 happenassert false : e;uri = null;}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, remainingMillis(deadlineMillis));return;}while (iProxy.hasNext()) {p = iProxy.next();if (p == null || p.type() != Proxy.Type.SOCKS) {super.connect(epoint, remainingMillis(deadlineMillis));return;}if (!(p.address() instanceof InetSocketAddress))throw new SocketException("Unknown address type for proxy: " + p);// Use getHostString() to avoid reverse lookupsserver = ((InetSocketAddress) p.address()).getHostString();serverPort = ((InetSocketAddress) p.address()).getPort();useV4 = useV4(p);// Connects to the SOCKS servertry {privilegedConnect(server, serverPort, remainingMillis(deadlineMillis));// Worked, let's get outta herebreak;} catch (IOException e) {// Ooops, let's notify the ProxySelectorsel.connectFailed(uri,p.address(),e);server = null;serverPort = -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 servertry {privilegedConnect(server, serverPort, remainingMillis(deadlineMillis));} catch (IOException e) {throw new SocketException(e.getMessage());}}// cmdIn & cmdOut were initialized during the privilegedConnect() callBufferedOutputStream 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, deadlineMillis);return;}// This is SOCKS V5out.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, deadlineMillis);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, deadlineMillis);return;}if (((int)data[1]) == NO_METHODS)throw new SocketException("SOCKS : No acceptable methods");if (!authenticate(data[1], in, out, deadlineMillis)) {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, deadlineMillis);if (i != 4)throw new SocketException("Reply from SOCKS server has bad length");SocketException ex = null;int len;byte[] addr;switch (data[1]) {case REQUEST_OK:// success!switch(data[3]) {case IPV4:addr = new byte[4];i = readSocksReply(in, addr, deadlineMillis);if (i != 4)throw new SocketException("Reply from SOCKS server badly formatted");data = new byte[2];i = readSocksReply(in, data, deadlineMillis);if (i != 2)throw new SocketException("Reply from SOCKS server badly formatted");break;case DOMAIN_NAME:byte[] lenByte = new byte[1];i = readSocksReply(in, lenByte, deadlineMillis);if (i != 1)throw new SocketException("Reply from SOCKS server badly formatted");len = lenByte[0] & 0xFF;byte[] host = new byte[len];i = readSocksReply(in, host, deadlineMillis);if (i != len)throw new SocketException("Reply from SOCKS server badly formatted");data = new byte[2];i = readSocksReply(in, data, deadlineMillis);if (i != 2)throw new SocketException("Reply from SOCKS server badly formatted");break;case IPV6:len = 16;addr = new byte[len];i = readSocksReply(in, addr, deadlineMillis);if (i != len)throw new SocketException("Reply from SOCKS server badly formatted");data = new byte[2];i = readSocksReply(in, data, deadlineMillis);if (i != 2)throw new SocketException("Reply from SOCKS server badly formatted");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 bindV4(InputStream in, OutputStream out,InetAddress baddr,int lport) throws IOException {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 = AccessController.doPrivileged(new PrivilegedAction<>() {public InetAddress run() {return 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 = getUserName();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;}}/*** Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind* means "accept incoming connection from", so the SocketAddress is* the one of the host we do accept connection from.** @param saddr the Socket address of the remote host.* @exception IOException if an I/O error occurs when binding this socket.*/protected synchronized void socksBind(InetSocketAddress saddr) throws IOException {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 serverif (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 ProxySelectorProxySelector sel = java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<>() {public ProxySelector run() {return ProxySelector.getDefault();}});if (sel == null) {/** No default proxySelector --> direct connection*/return;}URI uri;// Use getHostString() to avoid reverse lookupsString 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 happenassert false : e;uri = null;}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.type() != Proxy.Type.SOCKS) {return;}if (!(p.address() instanceof InetSocketAddress))throw new SocketException("Unknown address type for proxy: " + p);// Use getHostString() to avoid reverse lookupsserver = ((InetSocketAddress) p.address()).getHostString();serverPort = ((InetSocketAddress) p.address()).getPort();useV4 = useV4(p);// Connects to the SOCKS servertry {AccessController.doPrivileged(new PrivilegedExceptionAction<>() {public Void run() throws Exception {cmdsock = new Socket(new PlainSocketImpl());cmdsock.connect(new InetSocketAddress(server, serverPort));cmdIn = cmdsock.getInputStream();cmdOut = cmdsock.getOutputStream();return null;}});} catch (Exception e) {// Ooops, let's notify the ProxySelectorsel.connectFailed(uri,p.address(),new SocketException(e.getMessage()));server = null;serverPort = -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 Void run() throws Exception {cmdsock = new Socket(new PlainSocketImpl());cmdsock.connect(new InetSocketAddress(server, serverPort));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 upbindV4(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!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;}/*** Accepts a connection from a specific host.** @param s the accepted connection.* @param saddr the socket address of the host we do accept* connection from* @exception IOException if an I/O error occurs when accepting the* connection.*/protected void acceptFrom(SocketImpl s, InetSocketAddress saddr) throws IOException {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 psi = (PlainSocketImpl) s;psi.setInputStream((SocketInputStream) in);psi.setFileDescriptor(cmdsock.getImpl().getFileDescriptor());psi.setAddress(cmdsock.getImpl().getInetAddress());psi.setPort(cmdsock.getImpl().getPort());psi.setLocalPort(cmdsock.getImpl().getLocalPort());} else {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;}/*** Returns the value of this socket's {@code address} field.** @return the value of this socket's {@code address} field.* @see java.net.SocketImpl#address*/@Overrideprotected InetAddress getInetAddress() {if (external_address != null)return external_address.getAddress();elsereturn super.getInetAddress();}/*** Returns the value of this socket's {@code port} field.** @return the value of this socket's {@code port} field.* @see java.net.SocketImpl#port*/@Overrideprotected int getPort() {if (external_address != null)return external_address.getPort();elsereturn super.getPort();}@Overrideprotected int getLocalPort() {if (socket != null)return super.getLocalPort();if (external_address != null)return external_address.getPort();elsereturn super.getLocalPort();}@Overrideprotected void close() throws IOException {if (cmdsock != null)cmdsock.close();cmdsock = null;super.close();}private String getUserName() {String userName = "";if (applicationSetProxy) {try {userName = System.getProperty("user.name");} catch (SecurityException se) { /* swallow Exception */ }} else {userName = StaticProperty.userName();}return userName;}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。