< prev index next >

src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/AbstractAsyncSSLConnection.java

Print this page




  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.incubator.http;
  27 
  28 import java.io.IOException;
  29 import java.net.InetSocketAddress;
  30 import java.nio.ByteBuffer;



  31 import java.util.concurrent.CompletableFuture;


  32 import javax.net.ssl.SSLEngine;
  33 import jdk.incubator.http.internal.common.ExceptionallyCloseable;





  34 
  35 
  36 /**
  37  * Asynchronous version of SSLConnection.
  38  *
  39  * There are two concrete implementations of this class: AsyncSSLConnection
  40  * and AsyncSSLTunnelConnection.
  41  * This abstraction is useful when downgrading from HTTP/2 to HTTP/1.1 over
  42  * an SSL connection. See ExchangeImpl::get in the case where an ALPNException
  43  * is thrown.
  44  *
  45  * Note: An AsyncSSLConnection wraps a PlainHttpConnection, while an
  46  *       AsyncSSLTunnelConnection wraps a PlainTunnelingConnection.
  47  *       If both these wrapped classes where made to inherit from a
  48  *       common abstraction then it might be possible to merge
  49  *       AsyncSSLConnection and AsyncSSLTunnelConnection back into
  50  *       a single class - and simply use different factory methods to
  51  *       create different wrappees, but this is left up for further cleanup.
  52  *
  53  */
  54 abstract class AbstractAsyncSSLConnection extends HttpConnection
  55                implements AsyncConnection, ExceptionallyCloseable {
  56 
  57 
  58     AbstractAsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client) {





  59         super(addr, client);





  60     }
  61 
  62     abstract SSLEngine getEngine();
  63     abstract AsyncSSLDelegate sslDelegate();
  64     abstract HttpConnection plainConnection();
  65     abstract HttpConnection downgrade();

































  66 
  67     @Override
  68     final boolean isSecure() {
  69         return true;
  70     }
  71 
  72     // Blocking read functions not used here










































  73     @Override
  74     protected final ByteBuffer readImpl() throws IOException {
  75         throw new UnsupportedOperationException("Not supported.");





  76     }
  77 
  78     // whenReceivedResponse only used in HTTP/1.1 (Http1Exchange)
  79     // AbstractAsyncSSLConnection is only used with HTTP/2

  80     @Override
  81     final CompletableFuture<Void> whenReceivingResponse() {
  82         throw new UnsupportedOperationException("Not supported.");




  83     }
  84 
  85 }


  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.incubator.http;
  27 
  28 import java.io.IOException;
  29 import java.net.InetSocketAddress;
  30 import java.nio.ByteBuffer;
  31 import java.nio.channels.SocketChannel;
  32 import java.util.Arrays;
  33 import java.util.List;
  34 import java.util.concurrent.CompletableFuture;
  35 import javax.net.ssl.SNIHostName;
  36 import javax.net.ssl.SSLContext;
  37 import javax.net.ssl.SSLEngine;
  38 import javax.net.ssl.SSLEngineResult;
  39 import javax.net.ssl.SSLParameters;
  40 
  41 import jdk.incubator.http.internal.common.SSLTube;
  42 import jdk.incubator.http.internal.common.Log;
  43 import jdk.incubator.http.internal.common.Utils;
  44 
  45 
  46 /**
  47  * Asynchronous version of SSLConnection.
  48  *
  49  * There are two concrete implementations of this class: AsyncSSLConnection
  50  * and AsyncSSLTunnelConnection.
  51  * This abstraction is useful when downgrading from HTTP/2 to HTTP/1.1 over
  52  * an SSL connection. See ExchangeImpl::get in the case where an ALPNException
  53  * is thrown.
  54  *
  55  * Note: An AsyncSSLConnection wraps a PlainHttpConnection, while an
  56  *       AsyncSSLTunnelConnection wraps a PlainTunnelingConnection.
  57  *       If both these wrapped classes where made to inherit from a
  58  *       common abstraction then it might be possible to merge
  59  *       AsyncSSLConnection and AsyncSSLTunnelConnection back into
  60  *       a single class - and simply use different factory methods to
  61  *       create different wrappees, but this is left up for further cleanup.
  62  *
  63  */
  64 abstract class AbstractAsyncSSLConnection extends HttpConnection
  65 {
  66     protected final SSLEngine engine;
  67     protected final String serverName;
  68     protected final SSLParameters sslParameters;
  69 
  70     AbstractAsyncSSLConnection(InetSocketAddress addr,
  71                                HttpClientImpl client,
  72                                String serverName,
  73                                String[] alpn) {
  74         super(addr, client);
  75         this.serverName = serverName;
  76         SSLContext context = client.theSSLContext();
  77         sslParameters = createSSLParameters(client, serverName, alpn);
  78         Log.logParams(sslParameters);
  79         engine = createEngine(context, sslParameters);
  80     }
  81 


  82     abstract HttpConnection plainConnection();
  83     abstract SSLTube getConnectionFlow();
  84 
  85     final CompletableFuture<String> getALPN() {
  86         assert connected();
  87         return getConnectionFlow().getALPN();
  88     }
  89 
  90     final SSLEngine getEngine() { return engine; }
  91 
  92     private static SSLParameters createSSLParameters(HttpClientImpl client,
  93                                                      String serverName,
  94                                                      String[] alpn) {
  95         SSLParameters sslp = client.sslParameters();
  96         SSLParameters sslParameters = Utils.copySSLParameters(sslp);
  97         if (alpn != null) {
  98             Log.logSSL("AbstractAsyncSSLConnection: Setting application protocols: {0}",
  99                        Arrays.toString(alpn));
 100             sslParameters.setApplicationProtocols(alpn);
 101         } else {
 102             Log.logSSL("AbstractAsyncSSLConnection: no applications set!");
 103         }
 104         if (serverName != null) {
 105             sslParameters.setServerNames(List.of(new SNIHostName(serverName)));
 106         }
 107         return sslParameters;
 108     }
 109 
 110     private static SSLEngine createEngine(SSLContext context,
 111                                           SSLParameters sslParameters) {
 112         SSLEngine engine = context.createSSLEngine();
 113         engine.setUseClientMode(true);
 114         engine.setSSLParameters(sslParameters);
 115         return engine;
 116     }
 117 
 118     @Override
 119     final boolean isSecure() {
 120         return true;
 121     }
 122 
 123     // Support for WebSocket/RawChannelImpl which unfortunately
 124     // still depends on synchronous read/writes.
 125     // It should be removed when RawChannelImpl moves to using asynchronous APIs.
 126     static final class SSLConnectionChannel extends DetachedConnectionChannel {
 127         final DetachedConnectionChannel delegate;
 128         final SSLDelegate sslDelegate;
 129         SSLConnectionChannel(DetachedConnectionChannel delegate, SSLDelegate sslDelegate) {
 130             this.delegate = delegate;
 131             this.sslDelegate = sslDelegate;
 132         }
 133 
 134         SocketChannel channel() {
 135             return delegate.channel();
 136         }
 137 
 138         @Override
 139         ByteBuffer read() throws IOException {
 140             SSLDelegate.WrapperResult r = sslDelegate.recvData(ByteBuffer.allocate(8192));
 141             // TODO: check for closure
 142             int n = r.result.bytesProduced();
 143             if (n > 0) {
 144                 return r.buf;
 145             } else if (n == 0) {
 146                 return Utils.EMPTY_BYTEBUFFER;
 147             } else {
 148                 return null;
 149             }
 150         }
 151         @Override
 152         long write(ByteBuffer[] buffers, int start, int number) throws IOException {
 153             long l = SSLDelegate.countBytes(buffers, start, number);
 154             SSLDelegate.WrapperResult r = sslDelegate.sendData(buffers, start, number);
 155             if (r.result.getStatus() == SSLEngineResult.Status.CLOSED) {
 156                 if (l > 0) {
 157                     throw new IOException("SSLHttpConnection closed");
 158                 }
 159             }
 160             return l;
 161         }
 162         @Override
 163         public void shutdownInput() throws IOException {
 164             delegate.shutdownInput();
 165         }
 166         @Override
 167         public void shutdownOutput() throws IOException {
 168             delegate.shutdownOutput();
 169         }
 170         @Override
 171         public void close() {
 172             delegate.close();
 173         }
 174     }
 175 
 176     // Support for WebSocket/RawChannelImpl which unfortunately
 177     // still depends on synchronous read/writes.
 178     // It should be removed when RawChannelImpl moves to using asynchronous APIs.
 179     @Override
 180     DetachedConnectionChannel detachChannel() {
 181         assert client() != null;
 182         DetachedConnectionChannel detachedChannel = plainConnection().detachChannel();
 183         SSLDelegate sslDelegate = new SSLDelegate(engine,
 184                                                   detachedChannel.channel());
 185         return new SSLConnectionChannel(detachedChannel, sslDelegate);
 186     }
 187 
 188 }
< prev index next >