30 import java.lang.reflect.Method; |
30 import java.lang.reflect.Method; |
31 import java.util.HashMap; |
31 import java.util.HashMap; |
32 import java.util.Map; |
32 import java.util.Map; |
33 import java.util.Set; |
33 import java.util.Set; |
34 |
34 |
|
35 import sun.nio.ch.NioSocketImpl; |
|
36 |
35 /** |
37 /** |
36 * Basic SocketImpl that relies on the internal HTTP protocol handler |
38 * Basic SocketImpl that relies on the internal HTTP protocol handler |
37 * implementation to perform the HTTP tunneling and authentication. The |
39 * implementation to perform the HTTP tunneling and authentication. The |
38 * sockets impl is swapped out and replaced with the socket from the HTTP |
40 * sockets impl is swapped out and replaced with the socket from the HTTP |
39 * handler after the tunnel is successfully setup. |
41 * handler after the tunnel is successfully setup. |
40 * |
42 * |
41 * @since 1.8 |
43 * @since 1.8 |
42 */ |
44 */ |
43 |
45 |
44 /*package*/ class HttpConnectSocketImpl extends PlainSocketImpl { |
46 /*package*/ class HttpConnectSocketImpl extends NioSocketImpl { |
45 |
47 |
46 private static final String httpURLClazzStr = |
48 private static final String httpURLClazzStr = |
47 "sun.net.www.protocol.http.HttpURLConnection"; |
49 "sun.net.www.protocol.http.HttpURLConnection"; |
48 private static final String netClientClazzStr = "sun.net.NetworkClient"; |
50 private static final String netClientClazzStr = "sun.net.NetworkClient"; |
49 private static final String doTunnelingStr = "doTunneling"; |
51 private static final String doTunnelingStr = "doTunneling"; |
74 } catch (ReflectiveOperationException x) { |
76 } catch (ReflectiveOperationException x) { |
75 throw new InternalError("Should not reach here", x); |
77 throw new InternalError("Should not reach here", x); |
76 } |
78 } |
77 } |
79 } |
78 |
80 |
79 HttpConnectSocketImpl(String server, int port) { |
|
80 this.server = server; |
|
81 this.port = port; |
|
82 } |
|
83 |
|
84 HttpConnectSocketImpl(Proxy proxy) { |
81 HttpConnectSocketImpl(Proxy proxy) { |
|
82 super(false); |
85 SocketAddress a = proxy.address(); |
83 SocketAddress a = proxy.address(); |
86 if ( !(a instanceof InetSocketAddress) ) |
84 if ( !(a instanceof InetSocketAddress) ) |
87 throw new IllegalArgumentException("Unsupported address type"); |
85 throw new IllegalArgumentException("Unsupported address type"); |
88 |
86 |
89 InetSocketAddress ad = (InetSocketAddress) a; |
87 InetSocketAddress ad = (InetSocketAddress) a; |
90 server = ad.getHostString(); |
88 server = ad.getHostString(); |
91 port = ad.getPort(); |
89 port = ad.getPort(); |
|
90 } |
|
91 |
|
92 @Override |
|
93 protected void connect(String host, int port) throws IOException { |
|
94 connect(new InetSocketAddress(host, port), 0); |
|
95 } |
|
96 |
|
97 @Override |
|
98 protected void connect(InetAddress address, int port) throws IOException { |
|
99 connect(new InetSocketAddress(address, port), 0); |
92 } |
100 } |
93 |
101 |
94 @Override |
102 @Override |
95 protected void connect(SocketAddress endpoint, int timeout) |
103 protected void connect(SocketAddress endpoint, int timeout) |
96 throws IOException |
104 throws IOException |
115 |
123 |
116 // close the original socket impl and release its descriptor |
124 // close the original socket impl and release its descriptor |
117 close(); |
125 close(); |
118 |
126 |
119 // update the Sockets impl to the impl from the http Socket |
127 // update the Sockets impl to the impl from the http Socket |
120 AbstractPlainSocketImpl psi = (AbstractPlainSocketImpl) httpSocket.impl; |
128 SocketImpl si = httpSocket.impl; |
121 this.getSocket().impl = psi; |
129 ((SocketImpl) this).getSocket().setImpl(si); |
122 |
130 |
123 // best effort is made to try and reset options previously set |
131 // best effort is made to try and reset options previously set |
124 Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet(); |
132 Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet(); |
125 try { |
133 try { |
126 for(Map.Entry<Integer,Object> entry : options) { |
134 for(Map.Entry<Integer,Object> entry : options) { |
127 psi.setOption(entry.getKey(), entry.getValue()); |
135 si.setOption(entry.getKey(), entry.getValue()); |
128 } |
136 } |
129 } catch (IOException x) { /* gulp! */ } |
137 } catch (IOException x) { /* gulp! */ } |
130 } |
138 } |
131 |
139 |
132 @Override |
140 @Override |
161 { |
169 { |
162 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port)); |
170 Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(server, port)); |
163 URL destURL = new URL(urlString); |
171 URL destURL = new URL(urlString); |
164 HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy); |
172 HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy); |
165 conn.setConnectTimeout(connectTimeout); |
173 conn.setConnectTimeout(connectTimeout); |
166 conn.setReadTimeout(this.timeout); |
174 Object value = getOption(SocketOptions.SO_TIMEOUT); |
|
175 if (value != null) { |
|
176 Integer timeout = (Integer) value; |
|
177 conn.setReadTimeout(timeout); |
|
178 } |
167 conn.connect(); |
179 conn.connect(); |
168 doTunneling(conn); |
180 doTunneling(conn); |
169 try { |
181 try { |
170 Object httpClient = httpField.get(conn); |
182 Object httpClient = httpField.get(conn); |
171 return (Socket) serverSocketField.get(httpClient); |
183 return (Socket) serverSocketField.get(httpClient); |
195 if (external_address != null) |
207 if (external_address != null) |
196 return external_address.getPort(); |
208 return external_address.getPort(); |
197 else |
209 else |
198 return super.getPort(); |
210 return super.getPort(); |
199 } |
211 } |
200 |
|
201 @Override |
|
202 protected int getLocalPort() { |
|
203 if (socket != null) |
|
204 return super.getLocalPort(); |
|
205 if (external_address != null) |
|
206 return external_address.getPort(); |
|
207 else |
|
208 return super.getLocalPort(); |
|
209 } |
|
210 } |
212 } |