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