1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 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 * questions. 24 */ 25 26 package jdk.internal.net.http; 27 28 import java.net.InetSocketAddress; 29 import java.nio.channels.SocketChannel; 30 import java.util.concurrent.CompletableFuture; 31 import java.net.http.HttpHeaders; 32 import java.util.function.Function; 33 import jdk.internal.net.http.common.MinimalFuture; 34 import jdk.internal.net.http.common.SSLTube; 35 import jdk.internal.net.http.common.Utils; 36 37 /** 38 * An SSL tunnel built on a Plain (CONNECT) TCP tunnel. 39 */ 40 class AsyncSSLTunnelConnection extends AbstractAsyncSSLConnection { 41 42 final PlainTunnelingConnection plainConnection; 43 final PlainHttpPublisher writePublisher; 44 volatile SSLTube flow; 45 46 AsyncSSLTunnelConnection(InetSocketAddress addr, 47 HttpClientImpl client, 48 String[] alpn, 49 InetSocketAddress proxy, 50 HttpHeaders proxyHeaders) 51 { 52 super(addr, client, Utils.getServerName(addr), addr.getPort(), alpn); 53 this.plainConnection = new PlainTunnelingConnection(addr, proxy, client, proxyHeaders); 54 this.writePublisher = new PlainHttpPublisher(); 55 } 56 57 @Override 58 public CompletableFuture<Void> connectAsync(Exchange<?> exchange) { 59 if (debug.on()) debug.log("Connecting plain tunnel connection"); 60 // This will connect the PlainHttpConnection flow, so that 61 // its HttpSubscriber and HttpPublisher are subscribed to the 62 // SocketTube 63 return plainConnection 64 .connectAsync(exchange) 65 .thenApply( unused -> { 66 if (debug.on()) debug.log("creating SSLTube"); 67 // create the SSLTube wrapping the SocketTube, with the given engine 68 flow = new SSLTube(engine, 69 client().theExecutor(), 70 client().getSSLBufferSupplier()::recycle, 71 plainConnection.getConnectionFlow()); 72 return null;} ); 73 } 74 75 @Override 76 public CompletableFuture<Void> finishConnect() { 77 // The actual ALPN value, which may be the empty string, is not 78 // interesting at this point, only that the handshake has completed. 79 return getALPN() 80 .handle((String unused, Throwable ex) -> { 81 if (ex == null) { 82 return plainConnection.finishConnect(); 83 } else { 84 plainConnection.close(); 85 return MinimalFuture.<Void>failedFuture(ex); 86 } }) 87 .thenCompose(Function.identity()); 88 } 89 90 @Override 91 boolean isTunnel() { return true; } 92 93 @Override 94 boolean connected() { 95 return plainConnection.connected(); // && sslDelegate.connected(); 96 } 97 98 @Override 99 HttpPublisher publisher() { return writePublisher; } 100 101 @Override 102 public String toString() { 103 return "AsyncSSLTunnelConnection: " + super.toString(); 104 } 105 106 @Override 107 ConnectionPool.CacheKey cacheKey() { 108 return ConnectionPool.cacheKey(address, plainConnection.proxyAddr); 109 } 110 111 @Override 112 public void close() { 113 plainConnection.close(); 114 } 115 116 @Override 117 SocketChannel channel() { 118 return plainConnection.channel(); 119 } 120 121 @Override 122 boolean isProxied() { 123 return true; 124 } 125 126 @Override 127 SSLTube getConnectionFlow() { 128 return flow; 129 } 130 }