/** Copyright (c) 2010, 2013, 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.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import java.util.Set;/*** Basic SocketImpl that relies on the internal HTTP protocol handler* implementation to perform the HTTP tunneling and authentication. The* sockets impl is swapped out and replaced with the socket from the HTTP* handler after the tunnel is successfully setup.** @since 1.8*//*package*/ class HttpConnectSocketImpl extends PlainSocketImpl {private static final String httpURLClazzStr ="sun.net.www.protocol.http.HttpURLConnection";private static final String netClientClazzStr = "sun.net.NetworkClient";private static final String doTunnelingStr = "doTunneling";private static final Field httpField;private static final Field serverSocketField;private static final Method doTunneling;private final String server;private InetSocketAddress external_address;private HashMap<Integer, Object> optionsMap = new HashMap<>();static {try {Class<?> httpClazz = Class.forName(httpURLClazzStr, true, null);httpField = httpClazz.getDeclaredField("http");doTunneling = httpClazz.getDeclaredMethod(doTunnelingStr);Class<?> netClientClazz = Class.forName(netClientClazzStr, true, null);serverSocketField = netClientClazz.getDeclaredField("serverSocket");java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<>() {public Void run() {httpField.setAccessible(true);serverSocketField.setAccessible(true);return null;}});} catch (ReflectiveOperationException x) {throw new InternalError("Should not reach here", x);}}HttpConnectSocketImpl(String server, int port) {this.server = server;this.port = port;}HttpConnectSocketImpl(Proxy proxy) {SocketAddress a = proxy.address();if ( !(a instanceof InetSocketAddress) )throw new IllegalArgumentException("Unsupported address type");InetSocketAddress ad = (InetSocketAddress) a;server = ad.getHostString();port = ad.getPort();}@Overrideprotected void connect(SocketAddress endpoint, int timeout)throws IOException{if (endpoint == null || !(endpoint instanceof InetSocketAddress))throw new IllegalArgumentException("Unsupported address type");final InetSocketAddress epoint = (InetSocketAddress)endpoint;final String destHost = epoint.isUnresolved() ? epoint.getHostName(): epoint.getAddress().getHostAddress();final int destPort = epoint.getPort();SecurityManager security = System.getSecurityManager();if (security != null)security.checkConnect(destHost, destPort);// Connect to the HTTP proxy serverString urlString = "http://" + destHost + ":" + destPort;Socket httpSocket = privilegedDoTunnel(urlString, timeout);// Success!external_address = epoint;// close the original socket impl and release its descriptorclose();// update the Sockets impl to the impl from the http SocketAbstractPlainSocketImpl psi = (AbstractPlainSocketImpl) httpSocket.impl;this.getSocket().impl = psi;// best effort is made to try and reset options previously setSet<Map.Entry<Integer,Object>> options = optionsMap.entrySet();try {for(Map.Entry<Integer,Object> entry : options) {psi.setOption(entry.getKey(), entry.getValue());}} catch (IOException x) { /* gulp! */ }}@Overridepublic void setOption(int opt, Object val) throws SocketException {super.setOption(opt, val);if (external_address != null)return; // we're connected, just return// store options so that they can be re-applied to the impl after connectoptionsMap.put(opt, val);}private Socket privilegedDoTunnel(final String urlString,final int timeout)throws IOException{try {return java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<>() {public Socket run() throws IOException {return doTunnel(urlString, timeout);}});} catch (java.security.PrivilegedActionException pae) {throw (IOException) pae.getException();}}private Socket doTunnel(String urlString, int connectTimeout)throws IOException{Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port));URL destURL = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy);conn.setConnectTimeout(connectTimeout);conn.setReadTimeout(this.timeout);conn.connect();doTunneling(conn);try {Object httpClient = httpField.get(conn);return (Socket) serverSocketField.get(httpClient);} catch (IllegalAccessException x) {throw new InternalError("Should not reach here", x);}}private void doTunneling(HttpURLConnection conn) {try {doTunneling.invoke(conn);} catch (ReflectiveOperationException x) {throw new InternalError("Should not reach here", x);}}@Overrideprotected InetAddress getInetAddress() {if (external_address != null)return external_address.getAddress();elsereturn super.getInetAddress();}@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();}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。