6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 */ 24 package java.net.http; 25 26 import java.io.FileOutputStream; 27 import java.io.IOException; 28 import java.io.PrintStream; 29 import java.net.InetSocketAddress; 30 import java.nio.ByteBuffer; 31 import java.nio.channels.SocketChannel; 32 import java.util.concurrent.CompletableFuture; 33 import javax.net.ssl.SSLParameters; 34 35 /** 36 * Wraps socket channel layer and takes care of SSL also. 37 * 38 * Subtypes are: 39 * PlainHttpConnection: regular direct TCP connection to server 40 * PlainProxyConnection: plain text proxy connection 41 * PlainTunnelingConnection: opens plain text (CONNECT) tunnel to server 42 * SSLConnection: TLS channel direct to server 43 * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel 44 */ 45 abstract class HttpConnection implements BufferHandler { 46 47 // address we are connected to. Could be a server or a proxy 48 final InetSocketAddress address; 49 final HttpClientImpl client; 50 protected volatile ByteBuffer buffer; 51 52 HttpConnection(InetSocketAddress address, HttpClientImpl client) { 53 this.address = address; 54 this.client = client; 55 } 56 57 /** 58 * Public API to this class. addr is the ultimate destination. Any proxies 59 * etc are figured out from the request. Returns an instance of one of the 60 * following 61 * PlainHttpConnection 62 * PlainTunnelingConnection 63 * SSLConnection 64 * SSLTunnelConnection 65 * 66 * When object returned, connect() or connectAsync() must be called, which 67 * when it returns/completes, the connection is usable for requests. 68 */ 69 public static HttpConnection getConnection(InetSocketAddress addr, 70 HttpRequestImpl request) { 71 return getConnectionImpl(addr, request); 72 } 73 74 public abstract void connect() throws IOException, InterruptedException; 75 76 public abstract CompletableFuture<Void> connectAsync(); 77 78 /** 79 * Returns whether this connection is connected to its destination 80 */ 81 abstract boolean connected(); 82 83 abstract boolean isSecure(); 84 85 abstract boolean isProxied(); 86 87 /** 88 * Completes when the first byte of the response is available to be read. 89 */ 90 abstract CompletableFuture<Void> whenReceivingResponse(); 91 92 // must be called before reading any data off connection 93 // at beginning of response. 94 ByteBuffer getRemaining() { 95 ByteBuffer b = buffer; 96 buffer = null; 97 return b; 98 } 99 100 final boolean isOpen() { 101 return channel().isOpen(); 102 } 103 104 /* Returns either a plain HTTP connection or a plain tunnelling connection 105 * for proxied websockets */ 106 private static HttpConnection getPlainConnection(InetSocketAddress addr, 107 InetSocketAddress proxy, 108 HttpRequestImpl request) { 109 HttpClientImpl client = request.client(); 110 111 if (request.isWebSocket() && proxy != null) { 112 return new PlainTunnelingConnection(addr, 113 proxy, 114 client, 115 request.getAccessControlContext()); 116 } else { 117 if (proxy == null) { 118 return new PlainHttpConnection(addr, client); 119 } else { 120 return new PlainProxyConnection(proxy, client); 121 } 122 } 123 } 124 125 private static HttpConnection getSSLConnection(InetSocketAddress addr, 126 InetSocketAddress proxy, 127 HttpRequestImpl request, 128 String[] alpn) { 129 HttpClientImpl client = request.client(); 130 if (proxy != null) { 131 return new SSLTunnelConnection(addr, 132 client, 133 proxy, 134 request.getAccessControlContext()); 135 } else { 136 return new SSLConnection(addr, client, alpn); 137 } 138 } 139 140 /** 141 * Main factory method. Gets a HttpConnection, either cached or new if 142 * none available. 143 */ 144 private static HttpConnection getConnectionImpl(InetSocketAddress addr, 145 HttpRequestImpl request) { 146 HttpConnection c; 147 HttpClientImpl client = request.client(); 148 InetSocketAddress proxy = request.proxy(); 149 boolean secure = request.secure(); 150 ConnectionPool pool = client.connectionPool(); 151 String[] alpn = null; 152 153 if (secure && request.requestHttp2()) { 154 alpn = new String[1]; 155 alpn[0] = "h2"; 156 } 157 158 if (!secure) { 159 c = pool.getConnection(false, addr, proxy); 160 if (c != null) { 161 return c; 162 } else { 163 return getPlainConnection(addr, proxy, request); 164 } 165 } else { 166 c = pool.getConnection(true, addr, proxy); 167 if (c != null) { 168 return c; 169 } else { 170 return getSSLConnection(addr, proxy, request, alpn); 171 } 172 } 173 } 174 175 void returnToCache(HttpHeaders hdrs) { 176 if (hdrs == null) { 177 // the connection was closed by server 178 close(); 179 return; 180 } 181 if (!isOpen()) { 182 return; 183 } 184 ConnectionPool pool = client.connectionPool(); 185 boolean keepAlive = hdrs.firstValue("Connection") 186 .map((s) -> !s.equalsIgnoreCase("close")) 187 .orElse(true); 188 189 if (keepAlive) { 190 pool.returnToPool(this); 206 } 207 208 final void checkWrite(long expected, 209 ByteBuffer[] buffers, 210 int start, 211 int length) 212 throws IOException 213 { 214 long written = write(buffers, start, length); 215 if (written != expected) { 216 throw new IOException("incorrect number of bytes written"); 217 } 218 } 219 220 abstract SocketChannel channel(); 221 222 final InetSocketAddress address() { 223 return address; 224 } 225 226 void configureBlocking(boolean mode) throws IOException { 227 channel().configureBlocking(mode); 228 } 229 230 abstract ConnectionPool.CacheKey cacheKey(); 231 232 /* 233 static PrintStream ps; 234 235 static { 236 try { 237 String propval = Utils.getNetProperty("java.net.httpclient.showData"); 238 if (propval != null && propval.equalsIgnoreCase("true")) { 239 ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false); 240 } 241 } catch (IOException e) { 242 e.printStackTrace(); 243 } 244 } 245 246 synchronized final void debugPrint(String s, ByteBuffer b) { 247 ByteBuffer[] bufs = new ByteBuffer[1]; 248 bufs[0] = b; 249 debugPrint(s, bufs, 0, 1); 250 } 251 252 synchronized final void debugPrint(String s, 253 ByteBuffer[] bufs, 254 int start, 255 int number) { 256 if (ps == null) { 257 return; 258 } 259 260 ps.printf("\n%s:\n", s); 261 262 for (int i=start; i<start+number; i++) { 263 ByteBuffer b = bufs[i].duplicate(); 264 while (b.hasRemaining()) { 265 int c = b.get(); 266 if (c == 10) { 267 ps.printf("LF \n"); 268 } else if (c == 13) { 269 ps.printf(" CR "); 270 } else if (c == 0x20) { 271 ps.printf("_"); 272 } else if (c > 0x20 && c <= 0x7F) { 273 ps.printf("%c", (char)c); 274 } else { 275 ps.printf("0x%02x ", c); 276 } 277 } 278 } 279 ps.printf("\n---------------------\n"); 280 } 281 282 */ 283 284 // overridden in SSL only 285 SSLParameters sslParameters() { 286 return null; 287 } 288 289 // Methods to be implemented for Plain TCP and SSL 290 291 abstract long write(ByteBuffer[] buffers, int start, int number) 292 throws IOException; 293 294 abstract long write(ByteBuffer buffer) throws IOException; 295 296 /** 297 * Closes this connection, by returning the socket to its connection pool. 298 */ 299 abstract void close(); 300 301 /** 302 * Returns a ByteBuffer with data, or null if EOF. 303 */ 304 final ByteBuffer read() throws IOException { 305 return read(-1); 306 } 307 308 /** 309 * Puts position to limit and limit to capacity so we can resume reading 310 * into this buffer, but if required > 0 then limit may be reduced so that 311 * no more than required bytes are read next time. 312 */ 313 static void resumeChannelRead(ByteBuffer buf, int required) { 314 int limit = buf.limit(); 315 buf.position(limit); 316 int capacity = buf.capacity() - limit; 317 if (required > 0 && required < capacity) { 318 buf.limit(limit + required); 319 } else { 339 return buffer; 340 } 341 342 final int read(ByteBuffer buffer) throws IOException { 343 int n = readImpl(buffer); 344 return n; 345 } 346 347 /** Reads up to length bytes. */ 348 protected abstract ByteBuffer readImpl(int length) throws IOException; 349 350 /** Reads as much as possible into given buffer and returns amount read. */ 351 protected abstract int readImpl(ByteBuffer buffer) throws IOException; 352 353 @Override 354 public String toString() { 355 return "HttpConnection: " + channel().toString(); 356 } 357 358 @Override 359 public final ByteBuffer getBuffer() { 360 return client.getBuffer(); 361 } 362 363 @Override 364 public final void returnBuffer(ByteBuffer buffer) { 365 client.returnBuffer(buffer); 366 } 367 } | 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 */ 24 package java.net.http; 25 26 import java.io.Closeable; 27 import java.io.IOException; 28 import java.net.InetSocketAddress; 29 import java.nio.ByteBuffer; 30 import java.nio.channels.SocketChannel; 31 import java.util.concurrent.CompletableFuture; 32 import javax.net.ssl.SSLParameters; 33 34 /** 35 * Wraps socket channel layer and takes care of SSL also. 36 * 37 * Subtypes are: 38 * PlainHttpConnection: regular direct TCP connection to server 39 * PlainProxyConnection: plain text proxy connection 40 * PlainTunnelingConnection: opens plain text (CONNECT) tunnel to server 41 * SSLConnection: TLS channel direct to server 42 * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel 43 */ 44 abstract class HttpConnection implements BufferHandler, Closeable { 45 46 protected final static ByteBuffer emptyBuf = Utils.EMPTY_BYTEBUFFER; 47 48 enum Mode { 49 BLOCKING, 50 NON_BLOCKING, 51 ASYNC 52 } 53 54 protected Mode mode; 55 56 // address we are connected to. Could be a server or a proxy 57 final InetSocketAddress address; 58 final HttpClientImpl client; 59 protected volatile ByteBuffer buffer; 60 61 HttpConnection(InetSocketAddress address, HttpClientImpl client) { 62 this.address = address; 63 this.client = client; 64 this.buffer = emptyBuf; 65 } 66 67 /** 68 * Public API to this class. addr is the ultimate destination. Any proxies 69 * etc are figured out from the request. Returns an instance of one of the 70 * following 71 * PlainHttpConnection 72 * PlainTunnelingConnection 73 * SSLConnection 74 * SSLTunnelConnection 75 * 76 * When object returned, connect() or connectAsync() must be called, which 77 * when it returns/completes, the connection is usable for requests. 78 */ 79 public static HttpConnection getConnection(InetSocketAddress addr, 80 HttpRequestImpl request) { 81 return getConnectionImpl(addr, request, null); 82 } 83 84 /** 85 * Called specifically to get an async connection for HTTP/2 over SSL. 86 * 87 * @param addr 88 * @param request 89 * @param http2 90 * @return 91 */ 92 public static HttpConnection getConnection(InetSocketAddress addr, 93 HttpRequestImpl request, Http2Connection http2) { 94 95 return getConnectionImpl(addr, request, http2); 96 } 97 98 public abstract void connect() throws IOException, InterruptedException; 99 100 public abstract CompletableFuture<Void> connectAsync(); 101 102 /** 103 * Returns whether this connection is connected to its destination 104 */ 105 abstract boolean connected(); 106 107 abstract boolean isSecure(); 108 109 abstract boolean isProxied(); 110 111 /** 112 * Completes when the first byte of the response is available to be read. 113 */ 114 abstract CompletableFuture<Void> whenReceivingResponse(); 115 116 // must be called before reading any data off connection 117 // at beginning of response. 118 ByteBuffer getRemaining() { 119 ByteBuffer b = buffer; 120 buffer = emptyBuf; 121 return b; 122 } 123 124 final boolean isOpen() { 125 return channel().isOpen(); 126 } 127 128 /* Returns either a plain HTTP connection or a plain tunnelling connection 129 * for proxied websockets */ 130 private static HttpConnection getPlainConnection(InetSocketAddress addr, 131 InetSocketAddress proxy, 132 HttpRequestImpl request) { 133 HttpClientImpl client = request.client(); 134 135 if (request.isWebSocket() && proxy != null) { 136 return new PlainTunnelingConnection(addr, 137 proxy, 138 client, 139 request.getAccessControlContext()); 140 } else { 141 if (proxy == null) { 142 return new PlainHttpConnection(addr, client); 143 } else { 144 return new PlainProxyConnection(proxy, client); 145 } 146 } 147 } 148 149 private static HttpConnection getSSLConnection(InetSocketAddress addr, 150 InetSocketAddress proxy, HttpRequestImpl request, 151 String[] alpn, Http2Connection http2) { 152 HttpClientImpl client = request.client(); 153 if (proxy != null) { 154 return new SSLTunnelConnection(addr, 155 client, 156 proxy, 157 request.getAccessControlContext()); 158 } else if (http2 == null) { 159 return new SSLConnection(addr, client, alpn); 160 } else { 161 return new AsyncSSLConnection(addr, client, alpn); 162 } 163 } 164 165 /** 166 * Main factory method. Gets a HttpConnection, either cached or new if 167 * none available. 168 */ 169 private static HttpConnection getConnectionImpl(InetSocketAddress addr, 170 HttpRequestImpl request, Http2Connection http2) { 171 172 HttpConnection c; 173 HttpClientImpl client = request.client(); 174 InetSocketAddress proxy = request.proxy(); 175 boolean secure = request.secure(); 176 ConnectionPool pool = client.connectionPool(); 177 String[] alpn = null; 178 179 if (secure && request.requestHttp2()) { 180 alpn = new String[1]; 181 alpn[0] = "h2"; 182 } 183 184 if (!secure) { 185 c = pool.getConnection(false, addr, proxy); 186 if (c != null) { 187 return c; 188 } else { 189 return getPlainConnection(addr, proxy, request); 190 } 191 } else { 192 c = pool.getConnection(true, addr, proxy); 193 if (c != null) { 194 return c; 195 } else { 196 return getSSLConnection(addr, proxy, request, alpn, http2); 197 } 198 } 199 } 200 201 void returnToCache(HttpHeaders hdrs) { 202 if (hdrs == null) { 203 // the connection was closed by server 204 close(); 205 return; 206 } 207 if (!isOpen()) { 208 return; 209 } 210 ConnectionPool pool = client.connectionPool(); 211 boolean keepAlive = hdrs.firstValue("Connection") 212 .map((s) -> !s.equalsIgnoreCase("close")) 213 .orElse(true); 214 215 if (keepAlive) { 216 pool.returnToPool(this); 232 } 233 234 final void checkWrite(long expected, 235 ByteBuffer[] buffers, 236 int start, 237 int length) 238 throws IOException 239 { 240 long written = write(buffers, start, length); 241 if (written != expected) { 242 throw new IOException("incorrect number of bytes written"); 243 } 244 } 245 246 abstract SocketChannel channel(); 247 248 final InetSocketAddress address() { 249 return address; 250 } 251 252 synchronized void configureMode(Mode mode) throws IOException { 253 this.mode = mode; 254 if (mode == Mode.BLOCKING) 255 channel().configureBlocking(true); 256 else 257 channel().configureBlocking(false); 258 } 259 260 abstract ConnectionPool.CacheKey cacheKey(); 261 262 // overridden in SSL only 263 SSLParameters sslParameters() { 264 return null; 265 } 266 267 // Methods to be implemented for Plain TCP and SSL 268 269 abstract long write(ByteBuffer[] buffers, int start, int number) 270 throws IOException; 271 272 abstract long write(ByteBuffer buffer) throws IOException; 273 274 /** 275 * Closes this connection, by returning the socket to its connection pool. 276 */ 277 @Override 278 public abstract void close(); 279 280 /** 281 * Returns a ByteBuffer with data, or null if EOF. 282 */ 283 final ByteBuffer read() throws IOException { 284 return read(-1); 285 } 286 287 /** 288 * Puts position to limit and limit to capacity so we can resume reading 289 * into this buffer, but if required > 0 then limit may be reduced so that 290 * no more than required bytes are read next time. 291 */ 292 static void resumeChannelRead(ByteBuffer buf, int required) { 293 int limit = buf.limit(); 294 buf.position(limit); 295 int capacity = buf.capacity() - limit; 296 if (required > 0 && required < capacity) { 297 buf.limit(limit + required); 298 } else { 318 return buffer; 319 } 320 321 final int read(ByteBuffer buffer) throws IOException { 322 int n = readImpl(buffer); 323 return n; 324 } 325 326 /** Reads up to length bytes. */ 327 protected abstract ByteBuffer readImpl(int length) throws IOException; 328 329 /** Reads as much as possible into given buffer and returns amount read. */ 330 protected abstract int readImpl(ByteBuffer buffer) throws IOException; 331 332 @Override 333 public String toString() { 334 return "HttpConnection: " + channel().toString(); 335 } 336 337 @Override 338 public final ByteBuffer getBuffer(int n) { 339 return client.getBuffer(n); 340 } 341 342 @Override 343 public final void returnBuffer(ByteBuffer buffer) { 344 client.returnBuffer(buffer); 345 } 346 347 @Override 348 public final void setMinBufferSize(int n) { 349 client.setMinBufferSize(n); 350 } 351 } |