SSLConnection.java revision 16749:38e5d6e8a291
11556Srgrimes/*
21556Srgrimes * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
31556Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41556Srgrimes *
51556Srgrimes * This code is free software; you can redistribute it and/or modify it
61556Srgrimes * under the terms of the GNU General Public License version 2 only, as
71556Srgrimes * published by the Free Software Foundation.  Oracle designates this
81556Srgrimes * particular file as subject to the "Classpath" exception as provided
91556Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101556Srgrimes *
111556Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
121556Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131556Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141556Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151556Srgrimes * accompanied this code).
161556Srgrimes *
171556Srgrimes * You should have received a copy of the GNU General Public License version
181556Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191556Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201556Srgrimes *
211556Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221556Srgrimes * or visit www.oracle.com if you need additional information or have any
231556Srgrimes * questions.
241556Srgrimes */
251556Srgrimes
261556Srgrimespackage jdk.incubator.http;
271556Srgrimes
281556Srgrimesimport java.io.IOException;
291556Srgrimesimport java.net.InetSocketAddress;
301556Srgrimesimport java.nio.ByteBuffer;
311556Srgrimesimport java.nio.channels.SocketChannel;
321556Srgrimesimport java.util.concurrent.CompletableFuture;
331556Srgrimesimport javax.net.ssl.SSLEngineResult.Status;
341556Srgrimesimport javax.net.ssl.SSLParameters;
353044Sdgimport jdk.incubator.http.SSLDelegate.WrapperResult;
3617987Speter
371556Srgrimesimport jdk.incubator.http.internal.common.ByteBufferReference;
381556Srgrimesimport jdk.incubator.http.internal.common.MinimalFuture;
391556Srgrimesimport jdk.incubator.http.internal.common.Utils;
401556Srgrimes
411556Srgrimes/**
421556Srgrimes * An SSL connection built on a Plain TCP connection.
431556Srgrimes */
441556Srgrimesclass SSLConnection extends HttpConnection {
451556Srgrimes
4617987Speter    PlainHttpConnection delegate;
471556Srgrimes    SSLDelegate sslDelegate;
481556Srgrimes    final String[] alpn;
491556Srgrimes
501556Srgrimes    @Override
511556Srgrimes    public CompletableFuture<Void> connectAsync() {
521556Srgrimes        return delegate.connectAsync()
531556Srgrimes                .thenCompose((Void v) ->
5417987Speter                                MinimalFuture.supply( () -> {
551556Srgrimes                                    this.sslDelegate = new SSLDelegate(delegate.channel(), client, alpn);
561556Srgrimes                                    return null;
571556Srgrimes                                }));
581556Srgrimes    }
591556Srgrimes
601556Srgrimes    @Override
611556Srgrimes    public void connect() throws IOException {
621556Srgrimes        delegate.connect();
631556Srgrimes        this.sslDelegate = new SSLDelegate(delegate.channel(), client, alpn);
641556Srgrimes    }
6517987Speter
6617987Speter    SSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) {
6717987Speter        super(addr, client);
6817987Speter        this.alpn = ap;
6917987Speter        delegate = new PlainHttpConnection(addr, client);
7017987Speter    }
7117987Speter
7217987Speter    @Override
7317987Speter    SSLParameters sslParameters() {
7417987Speter        return sslDelegate.getSSLParameters();
7517987Speter    }
7617987Speter
7717987Speter    @Override
7817987Speter    public String toString() {
7917987Speter        return "SSLConnection: " + super.toString();
801556Srgrimes    }
811556Srgrimes
821556Srgrimes    private static long countBytes(ByteBuffer[] buffers, int start, int length) {
831556Srgrimes        long c = 0;
841556Srgrimes        for (int i=0; i<length; i++) {
851556Srgrimes            c+= buffers[start+i].remaining();
861556Srgrimes        }
871556Srgrimes        return c;
8817987Speter    }
8917987Speter
9017987Speter    @Override
9117987Speter    ConnectionPool.CacheKey cacheKey() {
9217987Speter        return ConnectionPool.cacheKey(address, null);
9317987Speter    }
941556Srgrimes
951556Srgrimes    @Override
9617987Speter    long write(ByteBuffer[] buffers, int start, int number) throws IOException {
971556Srgrimes        //debugPrint("Send", buffers, start, number);
981556Srgrimes        long l = countBytes(buffers, start, number);
991556Srgrimes        WrapperResult r = sslDelegate.sendData(buffers, start, number);
1001556Srgrimes        if (r.result.getStatus() == Status.CLOSED) {
1011556Srgrimes            if (l > 0) {
1021556Srgrimes                throw new IOException("SSLHttpConnection closed");
10317987Speter            }
10417987Speter        }
10517987Speter        return l;
10617987Speter    }
10717987Speter
10817987Speter    @Override
10917987Speter    long write(ByteBuffer buffer) throws IOException {
1101556Srgrimes        //debugPrint("Send", buffer);
11117987Speter        long l = buffer.remaining();
11217987Speter        WrapperResult r = sslDelegate.sendData(buffer);
11317987Speter        if (r.result.getStatus() == Status.CLOSED) {
11417987Speter            if (l > 0) {
11517987Speter                throw new IOException("SSLHttpConnection closed");
11617987Speter            }
1171556Srgrimes        }
11817987Speter        return l;
11917987Speter    }
12017987Speter
12117987Speter    @Override
12217987Speter    void writeAsync(ByteBufferReference[] buffers) throws IOException {
1231556Srgrimes        write(ByteBufferReference.toBuffers(buffers), 0, buffers.length);
1241556Srgrimes    }
1251556Srgrimes
1261556Srgrimes    @Override
1271556Srgrimes    void writeAsyncUnordered(ByteBufferReference[] buffers) throws IOException {
1281556Srgrimes        write(ByteBufferReference.toBuffers(buffers), 0, buffers.length);
1291556Srgrimes    }
1301556Srgrimes
1311556Srgrimes    @Override
1321556Srgrimes    void flushAsync() throws IOException {
1331556Srgrimes        // nothing to do
1341556Srgrimes    }
1351556Srgrimes
1361556Srgrimes    @Override
1371556Srgrimes    public void close() {
1381556Srgrimes        Utils.close(delegate.channel());
1391556Srgrimes    }
1401556Srgrimes
1411556Srgrimes    @Override
1421556Srgrimes    void shutdownInput() throws IOException {
1431556Srgrimes        delegate.channel().shutdownInput();
1441556Srgrimes    }
1451556Srgrimes
1461556Srgrimes    @Override
1471556Srgrimes    void shutdownOutput() throws IOException {
1481556Srgrimes        delegate.channel().shutdownOutput();
1491556Srgrimes    }
1501556Srgrimes
1511556Srgrimes    @Override
1521556Srgrimes    protected ByteBuffer readImpl() throws IOException {
1531556Srgrimes        ByteBuffer dst = ByteBuffer.allocate(8192);
1541556Srgrimes        int n = readImpl(dst);
1551556Srgrimes        if (n > 0) {
1561556Srgrimes            return dst;
1571556Srgrimes        } else if (n == 0) {
1581556Srgrimes            return Utils.EMPTY_BYTEBUFFER;
1591556Srgrimes        } else {
1601556Srgrimes            return null;
1611556Srgrimes        }
1621556Srgrimes    }
1631556Srgrimes
1641556Srgrimes    @Override
1651556Srgrimes    protected int readImpl(ByteBuffer buf) throws IOException {
1661556Srgrimes        // TODO: need to ensure that buf is big enough for application data
1671556Srgrimes        WrapperResult r = sslDelegate.recvData(buf);
1681556Srgrimes        // TODO: check for closure
16917525Sache        String s = "Receive) ";
1701556Srgrimes        //debugPrint(s, r.buf);
1711556Srgrimes        if (r.result.bytesProduced() > 0) {
1721556Srgrimes            assert buf == r.buf;
1731556Srgrimes        }
1741556Srgrimes        return r.result.bytesProduced();
1751556Srgrimes    }
1761556Srgrimes
17717987Speter    @Override
1781556Srgrimes    boolean connected() {
1791556Srgrimes        return delegate.connected();
1801556Srgrimes    }
1811556Srgrimes
1821556Srgrimes    @Override
1831556Srgrimes    SocketChannel channel() {
1841556Srgrimes        return delegate.channel();
1851556Srgrimes    }
18617987Speter
1871556Srgrimes    @Override
1881556Srgrimes    CompletableFuture<Void> whenReceivingResponse() {
1891556Srgrimes        return delegate.whenReceivingResponse();
1901556Srgrimes    }
1911556Srgrimes
1921556Srgrimes    @Override
1931556Srgrimes    boolean isSecure() {
1941556Srgrimes        return true;
1951556Srgrimes    }
1961556Srgrimes
1971556Srgrimes    @Override
1981556Srgrimes    boolean isProxied() {
1991556Srgrimes        return false;
2001556Srgrimes    }
2011556Srgrimes
2021556Srgrimes}
2031556Srgrimes