jdk/src/sample/share/nio/server/ChannelIOSecure.java
author emc
Wed, 05 Nov 2014 08:37:04 -0500
changeset 27386 784414cffd9a
parent 25859 3317bb8137f4
child 28059 e576535359cc
permissions -rw-r--r--
8035259: javac, incorrect shadowing of classes vs type parameters Summary: Cause javac to look at type variables first when resolving names in an extends/implements list Reviewed-by: mcimadamore, jlahoda
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 10292
diff changeset
     2
 * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * Redistribution and use in source and binary forms, with or without
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * modification, are permitted provided that the following conditions
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * are met:
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 *   - Redistributions of source code must retain the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *     notice, this list of conditions and the following disclaimer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 *   - Redistributions in binary form must reproduce the above copyright
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 *     notice, this list of conditions and the following disclaimer in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 *     documentation and/or other materials provided with the distribution.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    15
 *   - Neither the name of Oracle nor the names of its
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *     contributors may be used to endorse or promote products derived
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 *     from this software without specific prior written permission.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
10292
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    32
/*
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    33
 * This source code is provided to illustrate the usage of a given feature
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    34
 * or technique and has been deliberately simplified. Additional steps
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    35
 * required for a production-quality application, such as security checks,
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    36
 * input validation and proper error handling, might not be present in
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    37
 * this sample code.
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    38
 */
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    39
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 5506
diff changeset
    40
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.nio.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import java.nio.channels.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import javax.net.ssl.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import javax.net.ssl.SSLEngineResult.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * A helper class which performs I/O using the SSLEngine API.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * Each connection has a SocketChannel and a SSLEngine that is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * used through the lifetime of the Channel.  We allocate byte buffers
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * for use as the outbound and inbound network buffers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * <PRE>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 *               Application Data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *               src      requestBB
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *                |           ^
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 *                |     |     |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *                v     |     |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *           +----+-----|-----+----+
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *           |          |          |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 *           |       SSL|Engine    |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 *   wrap()  |          |          |  unwrap()
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *           | OUTBOUND | INBOUND  |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 *           |          |          |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 *           +----+-----|-----+----+
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 *                |     |     ^
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *                |     |     |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *                v           |
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *            outNetBB     inNetBB
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 *                   Net data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * </PRE>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * These buffers handle all of the intermediary data for the SSL
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * connection.  To make things easy, we'll require outNetBB be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * completely flushed before trying to wrap any more data, but we
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * could certainly remove that restriction by using larger buffers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * There are many, many ways to handle compute and I/O strategies.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * What follows is a relatively simple one.  The reader is encouraged
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * to develop the strategy that best fits the application.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * In most of the non-blocking operations in this class, we let the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * Selector tell us when we're ready to attempt an I/O operation (by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * application repeatedly calling our methods).  Another option would be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * to attempt the operation and return from the method when no forward
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * progress can be made.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * There's lots of room for enhancements and improvement in this example.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * We're checking for SSL/TLS end-of-stream truncation attacks via
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * sslEngine.closeInbound().  When you reach the end of a input stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 * via a read() returning -1 or an IOException, we call
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * sslEngine.closeInbound() to signal to the sslEngine that no more
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * input will be available.  If the peer's close_notify message has not
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * yet been received, this could indicate a trucation attack, in which
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * an attacker is trying to prematurely close the connection.   The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * closeInbound() will throw an exception if this condition were
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 * present.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * @author Brad R. Wetmore
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * @author Mark Reinhold
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
class ChannelIOSecure extends ChannelIO {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    private SSLEngine sslEngine = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    private int appBBSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    private int netBBSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * All I/O goes through these buffers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * It might be nice to use a cache of ByteBuffers so we're
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     * not alloc/dealloc'ing ByteBuffer's for each new SSLEngine.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * We use our superclass' requestBB for our application input buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * Outbound application data is supplied to us by our callers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    private ByteBuffer inNetBB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    private ByteBuffer outNetBB;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * An empty ByteBuffer for use when one isn't available, say
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * as a source buffer during initial handshake wraps or for close
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    private static ByteBuffer hsBB = ByteBuffer.allocate(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * The FileChannel we're currently transferTo'ing (reading).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    private ByteBuffer fileChannelBB = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * During our initial handshake, keep track of the next
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * SSLEngine operation that needs to occur:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
     *     NEED_WRAP/NEED_UNWRAP
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
     * Once the initial handshake has completed, we can short circuit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     * handshake checks with initialHSComplete.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    private HandshakeStatus initialHSStatus;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
    private boolean initialHSComplete;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     * We have received the shutdown request by our caller, and have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     * closed our outbound side.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    private boolean shutdown = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * Constructor for a secure ChannelIO variant.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    protected ChannelIOSecure(SocketChannel sc, boolean blocking,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            SSLContext sslc) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        super(sc, blocking);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
         * We're a server, so no need to use host/port variant.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
         * The first call for a server is a NEED_UNWRAP.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        sslEngine = sslc.createSSLEngine();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        sslEngine.setUseClientMode(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        initialHSStatus = HandshakeStatus.NEED_UNWRAP;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        initialHSComplete = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        // Create a buffer using the normal expected packet size we'll
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        // be getting.  This may change, depending on the peer's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        // SSL implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        netBBSize = sslEngine.getSession().getPacketBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        inNetBB = ByteBuffer.allocate(netBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        outNetBB = ByteBuffer.allocate(netBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        outNetBB.position(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        outNetBB.limit(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
     * Static factory method for creating a secure ChannelIO object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
     * We need to allocate different sized application data buffers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
     * based on whether we're secure or not.  We can't determine
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
     * this until our sslEngine is created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    static ChannelIOSecure getInstance(SocketChannel sc, boolean blocking,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            SSLContext sslc) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        ChannelIOSecure cio = new ChannelIOSecure(sc, blocking, sslc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        // Create a buffer using the normal expected application size we'll
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        // be getting.  This may change, depending on the peer's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        // SSL implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        cio.appBBSize = cio.sslEngine.getSession().getApplicationBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        cio.requestBB = ByteBuffer.allocate(cio.appBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        return cio;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
     * Calls up to the superclass to adjust the buffer size
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
     * by an appropriate increment.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
    protected void resizeRequestBB() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        resizeRequestBB(appBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     * Adjust the inbount network buffer to an appropriate size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
    private void resizeResponseBB() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        ByteBuffer bb = ByteBuffer.allocate(netBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        inNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        bb.put(inNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        inNetBB = bb;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
     * Writes bb to the SocketChannel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     * Returns true when the ByteBuffer has no remaining data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    private boolean tryFlush(ByteBuffer bb) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        super.write(bb);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        return !bb.hasRemaining();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * Perform any handshaking processing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * This variant is for Servers without SelectionKeys (e.g.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     * blocking).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    boolean doHandshake() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        return doHandshake(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     * Perform any handshaking processing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     * If a SelectionKey is passed, register for selectable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     * operations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     * In the blocking case, our caller will keep calling us until
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * we finish the handshake.  Our reads/writes will block as expected.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     * In the non-blocking case, we just received the selection notification
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * that this channel is ready for whatever the operation is, so give
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     * it a try.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     * return:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
     *          true when handshake is done.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
     *          false while handshake is in progress
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    boolean doHandshake(SelectionKey sk) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        SSLEngineResult result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        if (initialHSComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            return initialHSComplete;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
         * Flush out the outgoing buffer, if there's anything left in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
         * it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        if (outNetBB.hasRemaining()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            if (!tryFlush(outNetBB)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            // See if we need to switch from write to read mode.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
            switch (initialHSStatus) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
             * Is this the last buffer?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
            case FINISHED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
                initialHSComplete = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
                // Fall-through to reregister need for a Read.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            case NEED_UNWRAP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
                if (sk != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                    sk.interestOps(SelectionKey.OP_READ);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            return initialHSComplete;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        switch (initialHSStatus) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        case NEED_UNWRAP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
            if (sc.read(inNetBB) == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                sslEngine.closeInbound();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
                return initialHSComplete;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
needIO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            while (initialHSStatus == HandshakeStatus.NEED_UNWRAP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                resizeRequestBB();    // expected room for unwrap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                inNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                result = sslEngine.unwrap(inNetBB, requestBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                inNetBB.compact();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                initialHSStatus = result.getHandshakeStatus();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                switch (result.getStatus()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                case OK:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
                    switch (initialHSStatus) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                    case NOT_HANDSHAKING:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                        throw new IOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                            "Not handshaking during initial handshake");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                    case NEED_TASK:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                        initialHSStatus = doTasks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
                    case FINISHED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                        initialHSComplete = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                        break needIO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
                case BUFFER_UNDERFLOW:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
                    // Resize buffer if needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                    netBBSize = sslEngine.getSession().getPacketBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                    if (netBBSize > inNetBB.capacity()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                        resizeResponseBB();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                     * Need to go reread the Channel for more data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                    if (sk != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                        sk.interestOps(SelectionKey.OP_READ);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
                    break needIO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                case BUFFER_OVERFLOW:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                    // Reset the application buffer size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                    appBBSize =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                        sslEngine.getSession().getApplicationBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
                default: //CLOSED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                    throw new IOException("Received" + result.getStatus() +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                        "during initial handshaking");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            }  // "needIO" block.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
             * Just transitioned from read to write.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            if (initialHSStatus != HandshakeStatus.NEED_WRAP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            // Fall through and fill the write buffers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        case NEED_WRAP:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
             * The flush above guarantees the out buffer to be empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            outNetBB.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            result = sslEngine.wrap(hsBB, outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            outNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
            initialHSStatus = result.getHandshakeStatus();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            switch (result.getStatus()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            case OK:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
                if (initialHSStatus == HandshakeStatus.NEED_TASK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                    initialHSStatus = doTasks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                if (sk != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                    sk.interestOps(SelectionKey.OP_WRITE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
            default: // BUFFER_OVERFLOW/BUFFER_UNDERFLOW/CLOSED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                throw new IOException("Received" + result.getStatus() +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                        "during initial handshaking");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        default: // NOT_HANDSHAKING/NEED_TASK/FINISHED
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            throw new RuntimeException("Invalid Handshaking State" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                    initialHSStatus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        } // switch
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        return initialHSComplete;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
     * Do all the outstanding handshake tasks in the current Thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    private SSLEngineResult.HandshakeStatus doTasks() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        Runnable runnable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
         * We could run this in a separate thread, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
         * do in the current for now.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        while ((runnable = sslEngine.getDelegatedTask()) != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            runnable.run();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        return sslEngine.getHandshakeStatus();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
     * Read the channel for more information, then unwrap the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
     * (hopefully application) data we get.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     * If we run out of data, we'll return to our caller (possibly using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     * a Selector) to get notification that more is available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     * Each call to this method will perform at most one underlying read().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
    int read() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        SSLEngineResult result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
        if (!initialHSComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        int pos = requestBB.position();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        if (sc.read(inNetBB) == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
            sslEngine.closeInbound();  // probably throws exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            resizeRequestBB();    // expected room for unwrap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
            inNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            result = sslEngine.unwrap(inNetBB, requestBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
            inNetBB.compact();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
             * Could check here for a renegotation, but we're only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
             * doing a simple read/write, and won't have enough state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
             * transitions to do a complete handshake, so ignore that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
             * possibility.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            switch (result.getStatus()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
            case BUFFER_OVERFLOW:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                // Reset the application buffer size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                appBBSize = sslEngine.getSession().getApplicationBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            case BUFFER_UNDERFLOW:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                // Resize buffer if needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                netBBSize = sslEngine.getSession().getPacketBufferSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                if (netBBSize > inNetBB.capacity()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                    resizeResponseBB();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                    break; // break, next read will support larger buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
            case OK:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                    doTasks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
                throw new IOException("sslEngine error during data read: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                    result.getStatus());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        } while ((inNetBB.position() != 0) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            result.getStatus() != Status.BUFFER_UNDERFLOW);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        return (requestBB.position() - pos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
     * Try to write out as much as possible from the src buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
    int write(ByteBuffer src) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        if (!initialHSComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        return doWrite(src);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
     * Try to flush out any existing outbound data, then try to wrap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
     * anything new contained in the src buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
     * Return the number of bytes actually consumed from the buffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
     * but the data may actually be still sitting in the output buffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
     * waiting to be flushed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
    private int doWrite(ByteBuffer src) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        int retValue = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        if (outNetBB.hasRemaining() && !tryFlush(outNetBB)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            return retValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
         * The data buffer is empty, we can reuse the entire buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        outNetBB.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        SSLEngineResult result = sslEngine.wrap(src, outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        retValue = result.bytesConsumed();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        outNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        switch (result.getStatus()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        case OK:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                doTasks();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            throw new IOException("sslEngine error during data write: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                result.getStatus());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
         * Try to flush the data, regardless of whether or not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
         * it's been selected.  Odds of a write buffer being full
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
         * is less than a read buffer being empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        if (outNetBB.hasRemaining()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            tryFlush(outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        return retValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     * Perform a FileChannel.TransferTo on the socket channel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * We have to copy the data into an intermediary app ByteBuffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     * first, then send it through the SSLEngine.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
     * We return the number of bytes actually read out of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
     * filechannel.  However, the data may actually be stuck
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
     * in the fileChannelBB or the outNetBB.  The caller
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
     * is responsible for making sure to call dataFlush()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
     * before shutting down.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    long transferTo(FileChannel fc, long pos, long len) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        if (!initialHSComplete) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
        if (fileChannelBB == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
            fileChannelBB = ByteBuffer.allocate(appBBSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            fileChannelBB.limit(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        fileChannelBB.compact();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        int fileRead = fc.read(fileChannelBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        fileChannelBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
         * We ignore the return value here, we return the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
         * number of bytes actually consumed from the the file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
         * We'll flush the output buffer before we start shutting down.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        doWrite(fileChannelBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        return fileRead;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
     * Flush any remaining data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
     * Return true when the fileChannelBB and outNetBB are empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    boolean dataFlush() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        boolean fileFlushed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        if ((fileChannelBB != null) && fileChannelBB.hasRemaining()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            doWrite(fileChannelBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            fileFlushed = !fileChannelBB.hasRemaining();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        } else if (outNetBB.hasRemaining()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            tryFlush(outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        return (fileFlushed && !outNetBB.hasRemaining());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
     * Begin the shutdown process.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
     * Close out the SSLEngine if not already done so, then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
     * wrap our outgoing close_notify message and try to send it on.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
     * <P>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
     * Return true when we're done passing the shutdown messsages.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    boolean shutdown() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
        if (!shutdown) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            sslEngine.closeOutbound();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            shutdown = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        if (outNetBB.hasRemaining() && tryFlush(outNetBB)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
         * By RFC 2616, we can "fire and forget" our close_notify
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
         * message, so that's what we'll do here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        outNetBB.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        SSLEngineResult result = sslEngine.wrap(hsBB, outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        if (result.getStatus() != Status.CLOSED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            throw new SSLException("Improper close state");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        outNetBB.flip();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
         * We won't wait for a select here, but if this doesn't work,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
         * we'll cycle back through on the next select.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        if (outNetBB.hasRemaining()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            tryFlush(outNetBB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        return (!outNetBB.hasRemaining() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
                (result.getHandshakeStatus() != HandshakeStatus.NEED_WRAP));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
     * close() is not overridden
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
}