/*
 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.net.ssl;

import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;


/**
 * A class which enables secure communications using protocols such as
 * the Secure Sockets Layer (SSL) or
 * <A HREF="http://www.ietf.org/rfc/rfc2246.txt"> IETF RFC 2246 "Transport
 * Layer Security" (TLS) </A> protocols, but is transport independent.
 * <P>
 * The secure communications modes include: <UL>
 *
 *      <LI> <em>Integrity Protection</em>.  SSL/TLS protects against
 *      modification of messages by an active wiretapper.
 *
 *      <LI> <em>Authentication</em>.  In most modes, SSL/TLS provides
 *      peer authentication.  Servers are usually authenticated, and
 *      clients may be authenticated as requested by servers.
 *
 *      <LI> <em>Confidentiality (Privacy Protection)</em>.  In most
 *      modes, SSL/TLS encrypts data being sent between client and
 *      server.  This protects the confidentiality of data, so that
 *      passive wiretappers won't see sensitive data such as financial
 *      information or personal information of many kinds.
 *
 *      </UL>
 *
 * These kinds of protection are specified by a "cipher suite", which
 * is a combination of cryptographic algorithms used by a given SSL
 * connection.  During the negotiation process, the two endpoints must
 * agree on a cipher suite that is available in both environments.  If
 * there is no such suite in common, no SSL connection can be
 * established, and no data can be exchanged.
 * <P>
 * The cipher suite used is established by a negotiation process called
 * "handshaking".  The goal of this process is to create or rejoin a
 * "session", which may protect many connections over time.  After
 * handshaking has completed, you can access session attributes by
 * using the {@link #getSession()} method.
 * <P>
 * The <code>SSLSocket</code> class provides much of the same security
 * functionality, but all of the inbound and outbound data is
 * automatically transported using the underlying {@link
 * java.net.Socket Socket}, which by design uses a blocking model.
 * While this is appropriate for many applications, this model does not
 * provide the scalability required by large servers.
 * <P>
 * The primary distinction of an <code>SSLEngine</code> is that it
 * operates on inbound and outbound byte streams, independent of the
 * transport mechanism.  It is the responsibility of the
 * <code>SSLEngine</code> user to arrange for reliable I/O transport to
 * the peer.  By separating the SSL/TLS abstraction from the I/O
 * transport mechanism, the <code>SSLEngine</code> can be used for a
 * wide variety of I/O types, such as {@link
 * java.nio.channels.spi.AbstractSelectableChannel#configureBlocking(boolean)
 * non-blocking I/O (polling)}, {@link java.nio.channels.Selector
 * selectable non-blocking I/O}, {@link java.net.Socket Socket} and the
 * traditional Input/OutputStreams, local {@link java.nio.ByteBuffer
 * ByteBuffers} or byte arrays, <A
 * HREF="http://www.jcp.org/en/jsr/detail?id=203"> future asynchronous
 * I/O models </A>, and so on.
 * <P>
 * At a high level, the <code>SSLEngine</code> appears thus:
 *
 * <pre>
 *                   app data
 *
 *                |           ^
 *                |     |     |
 *                v     |     |
 *           +----+-----|-----+----+
 *           |          |          |
 *           |       SSL|Engine    |
 *   wrap()  |          |          |  unwrap()
 *           | OUTBOUND | INBOUND  |
 *           |          |          |
 *           +----+-----|-----+----+
 *                |     |     ^
 *                |     |     |
 *                v           |
 *
 *                   net data
 * </pre>
 * Application data (also known as plaintext or cleartext) is data which
 * is produced or consumed by an application.  Its counterpart is
 * network data, which consists of either handshaking and/or ciphertext
 * (encrypted) data, and destined to be transported via an I/O
 * mechanism.  Inbound data is data which has been received from the
 * peer, and outbound data is destined for the peer.
 * <P>
 * (In the context of an <code>SSLEngine</code>, the term "handshake
 * data" is taken to mean any data exchanged to establish and control a
 * secure connection.  Handshake data includes the SSL/TLS messages
 * "alert", "change_cipher_spec," and "handshake.")
 * <P>
 * There are five distinct phases to an <code>SSLEngine</code>.
 *
 * <OL>
 *     <li> Creation - The <code>SSLEngine</code> has been created and
 *     initialized, but has not yet been used.  During this phase, an
 *     application may set any <code>SSLEngine</code>-specific settings
 *     (enabled cipher suites, whether the <code>SSLEngine</code> should
 *     handshake in client or server mode, and so on).  Once
 *     handshaking has begun, though, any new settings (except
 *     client/server mode, see below) will be used for
 *     the next handshake.
 *
 *     <li> Initial Handshake - The initial handshake is a procedure by
 *     which the two peers exchange communication parameters until an
 *     SSLSession is established.  Application data can not be sent during
 *     this phase.
 *
 *     <li> Application Data - Once the communication parameters have
 *     been established and the handshake is complete, application data
 *     may flow through the <code>SSLEngine</code>.  Outbound
 *     application messages are encrypted and integrity protected,
 *     and inbound messages reverse the process.
 *
 *     <li>  Rehandshaking - Either side may request a renegotiation of
 *     the session at any time during the Application Data phase.  New
 *     handshaking data can be intermixed among the application data.
 *     Before starting the rehandshake phase, the application may
 *     reset the SSL/TLS communication parameters such as the list of
 *     enabled ciphersuites and whether to use client authentication,
 *     but can not change between client/server modes.  As before, once
 *     handshaking has begun, any new <code>SSLEngine</code>
 *     configuration settings will not be used until the next
 *     handshake.
 *
 *     <li>  Closure - When the connection is no longer needed, the
 *     application should close the <code>SSLEngine</code> and should
 *     send/receive any remaining messages to the peer before
 *     closing the underlying transport mechanism.  Once an engine is
 *     closed, it is not reusable:  a new <code>SSLEngine</code> must
 *     be created.
 * </OL>
 * An <code>SSLEngine</code> is created by calling {@link
 * SSLContext#createSSLEngine()} from an initialized
 * <code>SSLContext</code>.  Any configuration
 * parameters should be set before making the first call to
 * <code>wrap()</code>, <code>unwrap()</code>, or
 * <code>beginHandshake()</code>.  These methods all trigger the
 * initial handshake.
 * <P>
 * Data moves through the engine by calling {@link #wrap(ByteBuffer,
 * ByteBuffer) wrap()} or {@link #unwrap(ByteBuffer, ByteBuffer)
 * unwrap()} on outbound or inbound data, respectively.  Depending on
 * the state of the <code>SSLEngine</code>, a <code>wrap()</code> call
 * may consume application data from the source buffer and may produce
 * network data in the destination buffer.  The outbound data
 * may contain application and/or handshake data.  A call to
 * <code>unwrap()</code> will examine the source buffer and may
 * advance the handshake if the data is handshaking information, or
 * may place application data in the destination buffer if the data
 * is application.  The state of the underlying SSL/TLS algorithm
 * will determine when data is consumed and produced.
 * <P>
 * Calls to <code>wrap()</code> and <code>unwrap()</code> return an
 * <code>SSLEngineResult</code> which indicates the status of the
 * operation, and (optionally) how to interact with the engine to make
 * progress.
 * <P>
 * The <code>SSLEngine</code> produces/consumes complete SSL/TLS
 * packets only, and does not store application data internally between
 * calls to <code>wrap()/unwrap()</code>.  Thus input and output
 * <code>ByteBuffer</code>s must be sized appropriately to hold the
 * maximum record that can be produced.  Calls to {@link
 * SSLSession#getPacketBufferSize()} and {@link
 * SSLSession#getApplicationBufferSize()} should be used to determine
 * the appropriate buffer sizes.  The size of the outbound application
 * data buffer generally does not matter.  If buffer conditions do not
 * allow for the proper consumption/production of data, the application
 * must determine (via {@link SSLEngineResult}) and correct the
 * problem, and then try the call again.
 * <P>
 * For example, <code>unwrap()</code> will return a {@link
 * SSLEngineResult.Status#BUFFER_OVERFLOW} result if the engine
 * determines that there is not enough destination buffer space available.
 * Applications should call {@link SSLSession#getApplicationBufferSize()}
 * and compare that value with the space available in the destination buffer,
 * enlarging the buffer if necessary.  Similarly, if <code>unwrap()</code>
 * were to return a {@link SSLEngineResult.Status#BUFFER_UNDERFLOW}, the
 * application should call {@link SSLSession#getPacketBufferSize()} to ensure
 * that the source buffer has enough room to hold a record (enlarging if
 * necessary), and then obtain more inbound data.
 *
 * <pre>
 *   SSLEngineResult r = engine.unwrap(src, dst);
 *   switch (r.getStatus()) {
 *   BUFFER_OVERFLOW:
 *       // Could attempt to drain the dst buffer of any already obtained
 *       // data, but we'll just increase it to the size needed.
 *       int appSize = engine.getSession().getApplicationBufferSize();
 *       ByteBuffer b = ByteBuffer.allocate(appSize + dst.position());
 *       dst.flip();
 *       b.put(dst);
 *       dst = b;
 *       // retry the operation.
 *       break;
 *   BUFFER_UNDERFLOW:
 *       int netSize = engine.getSession().getPacketBufferSize();
 *       // Resize buffer if needed.
 *       if (netSize > dst.capacity()) {
 *           ByteBuffer b = ByteBuffer.allocate(netSize);
 *           src.flip();
 *           b.put(src);
 *           src = b;
 *       }
 *       // Obtain more inbound network data for src,
 *       // then retry the operation.
 *       break;
 *   // other cases: CLOSED, OK.
 *   }
 * </pre>
 *
 * <P>
 * Unlike <code>SSLSocket</code>, all methods of SSLEngine are
 * non-blocking.  <code>SSLEngine</code> implementations may
 * require the results of tasks that may take an extended period of
 * time to complete, or may even block.  For example, a TrustManager
 * may need to connect to a remote certificate validation service,
 * or a KeyManager might need to prompt a user to determine which
 * certificate to use as part of client authentication.  Additionally,
 * creating cryptographic signatures and verifying them can be slow,
 * seemingly blocking.
 * <P>
 * For any operation which may potentially block, the
 * <code>SSLEngine</code> will create a {@link java.lang.Runnable}
 * delegated task.  When <code>SSLEngineResult</code> indicates that a
 * delegated task result is needed, the application must call {@link
 * #getDelegatedTask()} to obtain an outstanding delegated task and
 * call its {@link java.lang.Runnable#run() run()} method (possibly using
 * a different thread depending on the compute strategy).  The
 * application should continue obtaining delegated tasks until no more
 * exist, and try the original operation again.
 * <P>
 * At the end of a communication session, applications should properly
 * close the SSL/TLS link.  The SSL/TLS protocols have closure handshake
 * messages, and these messages should be communicated to the peer
 * before releasing the <code>SSLEngine</code> and closing the
 * underlying transport mechanism.  A close can be initiated by one of:
 * an SSLException, an inbound closure handshake message, or one of the
 * close methods.  In all cases, closure handshake messages are
 * generated by the engine, and <code>wrap()</code> should be repeatedly
 * called until the resulting <code>SSLEngineResult</code>'s status
 * returns "CLOSED", or {@link #isOutboundDone()} returns true.  All
 * data obtained from the <code>wrap()</code> method should be sent to the
 * peer.
 * <P>
 * {@link #closeOutbound()} is used to signal the engine that the
 * application will not be sending any more data.
 * <P>
 * A peer will signal its intent to close by sending its own closure
 * handshake message.  After this message has been received and
 * processed by the local <code>SSLEngine</code>'s <code>unwrap()</code>
 * call, the application can detect the close by calling
 * <code>unwrap()</code> and looking for a <code>SSLEngineResult</code>
 * with status "CLOSED", or if {@link #isInboundDone()} returns true.
 * If for some reason the peer closes the communication link without
 * sending the proper SSL/TLS closure message, the application can
 * detect the end-of-stream and can signal the engine via {@link
 * #closeInbound()} that there will no more inbound messages to
 * process.  Some applications might choose to require orderly shutdown
 * messages from a peer, in which case they can check that the closure
 * was generated by a handshake message and not by an end-of-stream
 * condition.
 * <P>
 * There are two groups of cipher suites which you will need to know
 * about when managing cipher suites:
 *
 * <UL>
 *      <LI> <em>Supported</em> cipher suites:  all the suites which are
 *      supported by the SSL implementation.  This list is reported
 *      using {@link #getSupportedCipherSuites()}.
 *
 *      <LI> <em>Enabled</em> cipher suites, which may be fewer than
 *      the full set of supported suites.  This group is set using the
 *      {@link #setEnabledCipherSuites(String [])} method, and
 *      queried using the {@link #getEnabledCipherSuites()} method.
 *      Initially, a default set of cipher suites will be enabled on a
 *      new engine that represents the minimum suggested
 *      configuration.
 * </UL>
 *
 * Implementation defaults require that only cipher suites which
 * authenticate servers and provide confidentiality be enabled by
 * default.  Only if both sides explicitly agree to unauthenticated
 * and/or non-private (unencrypted) communications will such a
 * cipher suite be selected.
 * <P>
 * Each SSL/TLS connection must have one client and one server, thus
 * each endpoint must decide which role to assume.  This choice determines
 * who begins the handshaking process as well as which type of messages
 * should be sent by each party.  The method {@link
 * #setUseClientMode(boolean)} configures the mode.  Once the initial
 * handshaking has started, an <code>SSLEngine</code> can not switch
 * between client and server modes, even when performing renegotiations.
 * <P>
 * Applications might choose to process delegated tasks in different
 * threads.  When an <code>SSLEngine</code>
 * is created, the current {@link java.security.AccessControlContext}
 * is saved.  All future delegated tasks will be processed using this
 * context:  that is, all access control decisions will be made using the
 * context captured at engine creation.
 * <P>
 * <HR>
 *
 * <B>Concurrency Notes</B>:
 * There are two concurrency issues to be aware of:
 *
 * <OL>
 *      <li>The <code>wrap()</code> and <code>unwrap()</code> methods
 *      may execute concurrently of each other.
 *
 *      <li> The SSL/TLS protocols employ ordered packets.
 *      Applications must take care to ensure that generated packets
 *      are delivered in sequence.  If packets arrive
 *      out-of-order, unexpected or fatal results may occur.
 * <P>
 *      For example:
 * <P>
 *      <pre>
 *              synchronized (outboundLock) {
 *                  sslEngine.wrap(src, dst);
 *                  outboundQueue.put(dst);
 *              }
 *      </pre>
 *
 *      As a corollary, two threads must not attempt to call the same method
 *      (either <code>wrap()</code> or <code>unwrap()</code>) concurrently,
 *      because there is no way to guarantee the eventual packet ordering.
 * </OL>
 *
 * @see SSLContext
 * @see SSLSocket
 * @see SSLServerSocket
 * @see SSLSession
 * @see java.net.Socket
 *
 * @since 1.5
 * @author Brad R. Wetmore
 */

public abstract class SSLEngine {

    private String peerHost = null;
    private int peerPort = -1;

    /**
     * Constructor for an <code>SSLEngine</code> providing no hints
     * for an internal session reuse strategy.
     *
     * @see     SSLContext#createSSLEngine()
     * @see     SSLSessionContext
     */
    protected SSLEngine() {
    }

    /**
     * Constructor for an <code>SSLEngine</code>.
     * <P>
     * <code>SSLEngine</code> implementations may use the
     * <code>peerHost</code> and <code>peerPort</code> parameters as hints
     * for their internal session reuse strategy.
     * <P>
     * Some cipher suites (such as Kerberos) require remote hostname
     * information. Implementations of this class should use this
     * constructor to use Kerberos.
     * <P>
     * The parameters are not authenticated by the
     * <code>SSLEngine</code>.
     *
     * @param   peerHost the name of the peer host
     * @param   peerPort the port number of the peer
     * @see     SSLContext#createSSLEngine(String, int)
     * @see     SSLSessionContext
     */
    protected SSLEngine(String peerHost, int peerPort) {
        this.peerHost = peerHost;
        this.peerPort = peerPort;
    }

    /**
     * Returns the host name of the peer.
     * <P>
     * Note that the value is not authenticated, and should not be
     * relied upon.
     *
     * @return  the host name of the peer, or null if nothing is
     *          available.
     */
    public String getPeerHost() {
        return peerHost;
    }

    /**
     * Returns the port number of the peer.
     * <P>
     * Note that the value is not authenticated, and should not be
     * relied upon.
     *
     * @return  the port number of the peer, or -1 if nothing is
     *          available.
     */
    public int getPeerPort() {
        return peerPort;
    }

    /**
     * Attempts to encode a buffer of plaintext application data into
     * SSL/TLS network data.
     * <P>
     * An invocation of this method behaves in exactly the same manner
     * as the invocation:
     * <blockquote><pre>
     * {@link #wrap(ByteBuffer [], int, int, ByteBuffer)
     *     engine.wrap(new ByteBuffer [] { src }, 0, 1, dst);}
     * </pre</blockquote>
     *
     * @param   src
     *          a <code>ByteBuffer</code> containing outbound application data
     * @param   dst
     *          a <code>ByteBuffer</code> to hold outbound network data
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  ReadOnlyBufferException
     *          if the <code>dst</code> buffer is read-only.
     * @throws  IllegalArgumentException
     *          if either <code>src</code> or <code>dst</code>
     *          is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     #wrap(ByteBuffer [], int, int, ByteBuffer)
     */
    public SSLEngineResult wrap(ByteBuffer src,
            ByteBuffer dst) throws SSLException {
        return wrap(new ByteBuffer [] { src }, 0, 1, dst);
    }

    /**
     * Attempts to encode plaintext bytes from a sequence of data
     * buffers into SSL/TLS network data.
     * <P>
     * An invocation of this method behaves in exactly the same manner
     * as the invocation:
     * <blockquote><pre>
     * {@link #wrap(ByteBuffer [], int, int, ByteBuffer)
     *     engine.wrap(srcs, 0, srcs.length, dst);}
     * </pre</blockquote>
     *
     * @param   srcs
     *          an array of <code>ByteBuffers</code> containing the
     *          outbound application data
     * @param   dst
     *          a <code>ByteBuffer</code> to hold outbound network data
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  ReadOnlyBufferException
     *          if the <code>dst</code> buffer is read-only.
     * @throws  IllegalArgumentException
     *          if either <code>srcs</code> or <code>dst</code>
     *          is null, or if any element in <code>srcs</code> is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     #wrap(ByteBuffer [], int, int, ByteBuffer)
     */
    public SSLEngineResult wrap(ByteBuffer [] srcs,
            ByteBuffer dst) throws SSLException {
        if (srcs == null) {
            throw new IllegalArgumentException("src == null");
        }
        return wrap(srcs, 0, srcs.length, dst);
    }


    /**
     * Attempts to encode plaintext bytes from a subsequence of data
     * buffers into SSL/TLS network data.  This <i>"gathering"</i>
     * operation encodes, in a single invocation, a sequence of bytes
     * from one or more of a given sequence of buffers.  Gathering
     * wraps are often useful when implementing network protocols or
     * file formats that, for example, group data into segments
     * consisting of one or more fixed-length headers followed by a
     * variable-length body.  See
     * {@link java.nio.channels.GatheringByteChannel} for more
     * information on gathering, and {@link
     * java.nio.channels.GatheringByteChannel#write(ByteBuffer[],
     * int, int)} for more information on the subsequence
     * behavior.
     * <P>
     * Depending on the state of the SSLEngine, this method may produce
     * network data without consuming any application data (for example,
     * it may generate handshake data.)
     * <P>
     * The application is responsible for reliably transporting the
     * network data to the peer, and for ensuring that data created by
     * multiple calls to wrap() is transported in the same order in which
     * it was generated.  The application must properly synchronize
     * multiple calls to this method.
     * <P>
     * If this <code>SSLEngine</code> has not yet started its initial
     * handshake, this method will automatically start the handshake.
     * <P>
     * This method will attempt to produce one SSL/TLS packet, and will
     * consume as much source data as possible, but will never consume
     * more than the sum of the bytes remaining in each buffer.  Each
     * <code>ByteBuffer</code>'s position is updated to reflect the
     * amount of data consumed or produced.  The limits remain the
     * same.
     * <P>
     * The underlying memory used by the <code>srcs</code> and
     * <code>dst ByteBuffer</code>s must not be the same.
     * <P>
     * See the class description for more information on engine closure.
     *
     * @param   srcs
     *          an array of <code>ByteBuffers</code> containing the
     *          outbound application data
     * @param   offset
     *          The offset within the buffer array of the first buffer from
     *          which bytes are to be retrieved; it must be non-negative
     *          and no larger than <code>srcs.length</code>
     * @param   length
     *          The maximum number of buffers to be accessed; it must be
     *          non-negative and no larger than
     *          <code>srcs.length</code>&nbsp;-&nbsp;<code>offset</code>
     * @param   dst
     *          a <code>ByteBuffer</code> to hold outbound network data
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  IndexOutOfBoundsException
     *          if the preconditions on the <code>offset</code> and
     *          <code>length</code> parameters do not hold.
     * @throws  ReadOnlyBufferException
     *          if the <code>dst</code> buffer is read-only.
     * @throws  IllegalArgumentException
     *          if either <code>srcs</code> or <code>dst</code>
     *          is null, or if any element in the <code>srcs</code>
     *          subsequence specified is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     java.nio.channels.GatheringByteChannel
     * @see     java.nio.channels.GatheringByteChannel#write(
     *              ByteBuffer[], int, int)
     */
    public abstract SSLEngineResult wrap(ByteBuffer [] srcs, int offset,
            int length, ByteBuffer dst) throws SSLException;

    /**
     * Attempts to decode SSL/TLS network data into a plaintext
     * application data buffer.
     * <P>
     * An invocation of this method behaves in exactly the same manner
     * as the invocation:
     * <blockquote><pre>
     * {@link #unwrap(ByteBuffer, ByteBuffer [], int, int)
     *     engine.unwrap(src, new ByteBuffer [] { dst }, 0, 1);}
     * </pre</blockquote>
     *
     * @param   src
     *          a <code>ByteBuffer</code> containing inbound network data.
     * @param   dst
     *          a <code>ByteBuffer</code> to hold inbound application data.
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  ReadOnlyBufferException
     *          if the <code>dst</code> buffer is read-only.
     * @throws  IllegalArgumentException
     *          if either <code>src</code> or <code>dst</code>
     *          is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     #unwrap(ByteBuffer, ByteBuffer [], int, int)
     */
    public SSLEngineResult unwrap(ByteBuffer src,
            ByteBuffer dst) throws SSLException {
        return unwrap(src, new ByteBuffer [] { dst }, 0, 1);
    }

    /**
     * Attempts to decode SSL/TLS network data into a sequence of plaintext
     * application data buffers.
     * <P>
     * An invocation of this method behaves in exactly the same manner
     * as the invocation:
     * <blockquote><pre>
     * {@link #unwrap(ByteBuffer, ByteBuffer [], int, int)
     *     engine.unwrap(src, dsts, 0, dsts.length);}
     * </pre</blockquote>
     *
     * @param   src
     *          a <code>ByteBuffer</code> containing inbound network data.
     * @param   dsts
     *          an array of <code>ByteBuffer</code>s to hold inbound
     *          application data.
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  ReadOnlyBufferException
     *          if any of the <code>dst</code> buffers are read-only.
     * @throws  IllegalArgumentException
     *          if either <code>src</code> or <code>dsts</code>
     *          is null, or if any element in <code>dsts</code> is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     #unwrap(ByteBuffer, ByteBuffer [], int, int)
     */
    public SSLEngineResult unwrap(ByteBuffer src,
            ByteBuffer [] dsts) throws SSLException {
        if (dsts == null) {
            throw new IllegalArgumentException("dsts == null");
        }
        return unwrap(src, dsts, 0, dsts.length);
    }

    /**
     * Attempts to decode SSL/TLS network data into a subsequence of
     * plaintext application data buffers.  This <i>"scattering"</i>
     * operation decodes, in a single invocation, a sequence of bytes
     * into one or more of a given sequence of buffers.  Scattering
     * unwraps are often useful when implementing network protocols or
     * file formats that, for example, group data into segments
     * consisting of one or more fixed-length headers followed by a
     * variable-length body.  See
     * {@link java.nio.channels.ScatteringByteChannel} for more
     * information on scattering, and {@link
     * java.nio.channels.ScatteringByteChannel#read(ByteBuffer[],
     * int, int)} for more information on the subsequence
     * behavior.
     * <P>
     * Depending on the state of the SSLEngine, this method may consume
     * network data without producing any application data (for example,
     * it may consume handshake data.)
     * <P>
     * The application is responsible for reliably obtaining the network
     * data from the peer, and for invoking unwrap() on the data in the
     * order it was received.  The application must properly synchronize
     * multiple calls to this method.
     * <P>
     * If this <code>SSLEngine</code> has not yet started its initial
     * handshake, this method will automatically start the handshake.
     * <P>
     * This method will attempt to consume one complete SSL/TLS network
     * packet, but will never consume more than the sum of the bytes
     * remaining in the buffers.  Each <code>ByteBuffer</code>'s
     * position is updated to reflect the amount of data consumed or
     * produced.  The limits remain the same.
     * <P>
     * The underlying memory used by the <code>src</code> and
     * <code>dsts ByteBuffer</code>s must not be the same.
     * <P>
     * The inbound network buffer may be modified as a result of this
     * call:  therefore if the network data packet is required for some
     * secondary purpose, the data should be duplicated before calling this
     * method.  Note:  the network data will not be useful to a second
     * SSLEngine, as each SSLEngine contains unique random state which
     * influences the SSL/TLS messages.
     * <P>
     * See the class description for more information on engine closure.
     *
     * @param   src
     *          a <code>ByteBuffer</code> containing inbound network data.
     * @param   dsts
     *          an array of <code>ByteBuffer</code>s to hold inbound
     *          application data.
     * @param   offset
     *          The offset within the buffer array of the first buffer from
     *          which bytes are to be transferred; it must be non-negative
     *          and no larger than <code>dsts.length</code>.
     * @param   length
     *          The maximum number of buffers to be accessed; it must be
     *          non-negative and no larger than
     *          <code>dsts.length</code>&nbsp;-&nbsp;<code>offset</code>.
     * @return  an <code>SSLEngineResult</code> describing the result
     *          of this operation.
     * @throws  SSLException
     *          A problem was encountered while processing the
     *          data that caused the <code>SSLEngine</code> to abort.
     *          See the class description for more information on
     *          engine closure.
     * @throws  IndexOutOfBoundsException
     *          If the preconditions on the <code>offset</code> and
     *          <code>length</code> parameters do not hold.
     * @throws  ReadOnlyBufferException
     *          if any of the <code>dst</code> buffers are read-only.
     * @throws  IllegalArgumentException
     *          if either <code>src</code> or <code>dsts</code>
     *          is null, or if any element in the <code>dsts</code>
     *          subsequence specified is null.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     java.nio.channels.ScatteringByteChannel
     * @see     java.nio.channels.ScatteringByteChannel#read(
     *              ByteBuffer[], int, int)
     */
    public abstract SSLEngineResult unwrap(ByteBuffer src,
            ByteBuffer [] dsts, int offset, int length) throws SSLException;


    /**
     * Returns a delegated <code>Runnable</code> task for
     * this <code>SSLEngine</code>.
     * <P>
     * <code>SSLEngine</code> operations may require the results of
     * operations that block, or may take an extended period of time to
     * complete.  This method is used to obtain an outstanding {@link
     * java.lang.Runnable} operation (task).  Each task must be assigned
     * a thread (possibly the current) to perform the {@link
     * java.lang.Runnable#run() run} operation.  Once the
     * <code>run</code> method returns, the <code>Runnable</code> object
     * is no longer needed and may be discarded.
     * <P>
     * Delegated tasks run in the <code>AccessControlContext</code>
     * in place when this object was created.
     * <P>
     * A call to this method will return each outstanding task
     * exactly once.
     * <P>
     * Multiple delegated tasks can be run in parallel.
     *
     * @return  a delegated <code>Runnable</code> task, or null
     *          if none are available.
     */
    public abstract Runnable getDelegatedTask();


    /**
     * Signals that no more inbound network data will be sent
     * to this <code>SSLEngine</code>.
     * <P>
     * If the application initiated the closing process by calling
     * {@link #closeOutbound()}, under some circumstances it is not
     * required that the initiator wait for the peer's corresponding
     * close message.  (See section 7.2.1 of the TLS specification (<A
     * HREF="http://www.ietf.org/rfc/rfc2246.txt">RFC 2246</A>) for more
     * information on waiting for closure alerts.)  In such cases, this
     * method need not be called.
     * <P>
     * But if the application did not initiate the closure process, or
     * if the circumstances above do not apply, this method should be
     * called whenever the end of the SSL/TLS data stream is reached.
     * This ensures closure of the inbound side, and checks that the
     * peer followed the SSL/TLS close procedure properly, thus
     * detecting possible truncation attacks.
     * <P>
     * This method is idempotent:  if the inbound side has already
     * been closed, this method does not do anything.
     * <P>
     * {@link #wrap(ByteBuffer, ByteBuffer) wrap()} should be
     * called to flush any remaining handshake data.
     *
     * @throws  SSLException
     *          if this engine has not received the proper SSL/TLS close
     *          notification message from the peer.
     *
     * @see     #isInboundDone()
     * @see     #isOutboundDone()
     */
    public abstract void closeInbound() throws SSLException;


    /**
     * Returns whether {@link #unwrap(ByteBuffer, ByteBuffer)} will
     * accept any more inbound data messages.
     *
     * @return  true if the <code>SSLEngine</code> will not
     *          consume anymore network data (and by implication,
     *          will not produce any more application data.)
     * @see     #closeInbound()
     */
    public abstract boolean isInboundDone();


    /**
     * Signals that no more outbound application data will be sent
     * on this <code>SSLEngine</code>.
     * <P>
     * This method is idempotent:  if the outbound side has already
     * been closed, this method does not do anything.
     * <P>
     * {@link #wrap(ByteBuffer, ByteBuffer)} should be
     * called to flush any remaining handshake data.
     *
     * @see     #isOutboundDone()
     */
    public abstract void closeOutbound();


    /**
     * Returns whether {@link #wrap(ByteBuffer, ByteBuffer)} will
     * produce any more outbound data messages.
     * <P>
     * Note that during the closure phase, a <code>SSLEngine</code> may
     * generate handshake closure data that must be sent to the peer.
     * <code>wrap()</code> must be called to generate this data.  When
     * this method returns true, no more outbound data will be created.
     *
     * @return  true if the <code>SSLEngine</code> will not produce
     *          any more network data
     *
     * @see     #closeOutbound()
     * @see     #closeInbound()
     */
    public abstract boolean isOutboundDone();


    /**
     * Returns the names of the cipher suites which could be enabled for use
     * on this engine.  Normally, only a subset of these will actually
     * be enabled by default, since this list may include cipher suites which
     * do not meet quality of service requirements for those defaults.  Such
     * cipher suites might be useful in specialized applications.
     *
     * @return  an array of cipher suite names
     * @see     #getEnabledCipherSuites()
     * @see     #setEnabledCipherSuites(String [])
     */
    public abstract String [] getSupportedCipherSuites();


    /**
     * Returns the names of the SSL cipher suites which are currently
     * enabled for use on this engine.  When an SSLEngine is first
     * created, all enabled cipher suites support a minimum quality of
     * service.  Thus, in some environments this value might be empty.
     * <P>
     * Even if a suite has been enabled, it might never be used.  (For
     * example, the peer does not support it, the requisite
     * certificates/private keys for the suite are not available, or an
     * anonymous suite is enabled but authentication is required.)
     *
     * @return  an array of cipher suite names
     * @see     #getSupportedCipherSuites()
     * @see     #setEnabledCipherSuites(String [])
     */
    public abstract String [] getEnabledCipherSuites();


    /**
     * Sets the cipher suites enabled for use on this engine.
     * <P>
     * Each cipher suite in the <code>suites</code> parameter must have
     * been listed by getSupportedCipherSuites(), or the method will
     * fail.  Following a successful call to this method, only suites
     * listed in the <code>suites</code> parameter are enabled for use.
     * <P>
     * See {@link #getEnabledCipherSuites()} for more information
     * on why a specific cipher suite may never be used on a engine.
     *
     * @param   suites Names of all the cipher suites to enable
     * @throws  IllegalArgumentException when one or more of the ciphers
     *          named by the parameter is not supported, or when the
     *          parameter is null.
     * @see     #getSupportedCipherSuites()
     * @see     #getEnabledCipherSuites()
     */
    public abstract void setEnabledCipherSuites(String suites []);


    /**
     * Returns the names of the protocols which could be enabled for use
     * with this <code>SSLEngine</code>.
     *
     * @return  an array of protocols supported
     */
    public abstract String [] getSupportedProtocols();


    /**
     * Returns the names of the protocol versions which are currently
     * enabled for use with this <code>SSLEngine</code>.
     *
     * @return  an array of protocols
     * @see     #setEnabledProtocols(String [])
     */
    public abstract String [] getEnabledProtocols();


    /**
     * Set the protocol versions enabled for use on this engine.
     * <P>
     * The protocols must have been listed by getSupportedProtocols()
     * as being supported.  Following a successful call to this method,
     * only protocols listed in the <code>protocols</code> parameter
     * are enabled for use.
     *
     * @param   protocols Names of all the protocols to enable.
     * @throws  IllegalArgumentException when one or more of
     *          the protocols named by the parameter is not supported or
     *          when the protocols parameter is null.
     * @see     #getEnabledProtocols()
     */
    public abstract void setEnabledProtocols(String protocols[]);


    /**
     * Returns the <code>SSLSession</code> in use in this
     * <code>SSLEngine</code>.
     * <P>
     * These can be long lived, and frequently correspond to an entire
     * login session for some user.  The session specifies a particular
     * cipher suite which is being actively used by all connections in
     * that session, as well as the identities of the session's client
     * and server.
     * <P>
     * Unlike {@link SSLSocket#getSession()}
     * this method does not block until handshaking is complete.
     * <P>
     * Until the initial handshake has completed, this method returns
     * a session object which reports an invalid cipher suite of
     * "SSL_NULL_WITH_NULL_NULL".
     *
     * @return  the <code>SSLSession</code> for this <code>SSLEngine</code>
     * @see     SSLSession
     */
    public abstract SSLSession getSession();


    /**
     * Initiates handshaking (initial or renegotiation) on this SSLEngine.
     * <P>
     * This method is not needed for the initial handshake, as the
     * <code>wrap()</code> and <code>unwrap()</code> methods will
     * implicitly call this method if handshaking has not already begun.
     * <P>
     * Note that the peer may also request a session renegotiation with
     * this <code>SSLEngine</code> by sending the appropriate
     * session renegotiate handshake message.
     * <P>
     * Unlike the {@link SSLSocket#startHandshake()
     * SSLSocket#startHandshake()} method, this method does not block
     * until handshaking is completed.
     * <P>
     * To force a complete SSL/TLS session renegotiation, the current
     * session should be invalidated prior to calling this method.
     * <P>
     * Some protocols may not support multiple handshakes on an existing
     * engine and may throw an <code>SSLException</code>.
     *
     * @throws  SSLException
     *          if a problem was encountered while signaling the
     *          <code>SSLEngine</code> to begin a new handshake.
     *          See the class description for more information on
     *          engine closure.
     * @throws  IllegalStateException if the client/server mode
     *          has not yet been set.
     * @see     SSLSession#invalidate()
     */
    public abstract void beginHandshake() throws SSLException;


    /**
     * Returns the current handshake status for this <code>SSLEngine</code>.
     *
     * @return  the current <code>SSLEngineResult.HandshakeStatus</code>.
     */
    public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus();


    /**
     * Configures the engine to use client (or server) mode when
     * handshaking.
     * <P>
     * This method must be called before any handshaking occurs.
     * Once handshaking has begun, the mode can not be reset for the
     * life of this engine.
     * <P>
     * Servers normally authenticate themselves, and clients
     * are not required to do so.
     *
     * @param   mode true if the engine should start its handshaking
     *          in "client" mode
     * @throws  IllegalArgumentException if a mode change is attempted
     *          after the initial handshake has begun.
     * @see     #getUseClientMode()
     */
    public abstract void setUseClientMode(boolean mode);


    /**
     * Returns true if the engine is set to use client mode when
     * handshaking.
     *
     * @return  true if the engine should do handshaking
     *          in "client" mode
     * @see     #setUseClientMode(boolean)
     */
    public abstract boolean getUseClientMode();


    /**
     * Configures the engine to <i>require</i> client authentication.  This
     * option is only useful for engines in the server mode.
     * <P>
     * An engine's client authentication setting is one of the following:
     * <ul>
     * <li> client authentication required
     * <li> client authentication requested
     * <li> no client authentication desired
     * </ul>
     * <P>
     * Unlike {@link #setWantClientAuth(boolean)}, if this option is set and
     * the client chooses not to provide authentication information
     * about itself, <i>the negotiations will stop and the engine will
     * begin its closure procedure</i>.
     * <P>
     * Calling this method overrides any previous setting made by
     * this method or {@link #setWantClientAuth(boolean)}.
     *
     * @param   need set to true if client authentication is required,
     *          or false if no client authentication is desired.
     * @see     #getNeedClientAuth()
     * @see     #setWantClientAuth(boolean)
     * @see     #getWantClientAuth()
     * @see     #setUseClientMode(boolean)
     */
    public abstract void setNeedClientAuth(boolean need);


    /**
     * Returns true if the engine will <i>require</i> client authentication.
     * This option is only useful to engines in the server mode.
     *
     * @return  true if client authentication is required,
     *          or false if no client authentication is desired.
     * @see     #setNeedClientAuth(boolean)
     * @see     #setWantClientAuth(boolean)
     * @see     #getWantClientAuth()
     * @see     #setUseClientMode(boolean)
     */
    public abstract boolean getNeedClientAuth();


    /**
     * Configures the engine to <i>request</i> client authentication.
     * This option is only useful for engines in the server mode.
     * <P>
     * An engine's client authentication setting is one of the following:
     * <ul>
     * <li> client authentication required
     * <li> client authentication requested
     * <li> no client authentication desired
     * </ul>
     * <P>
     * Unlike {@link #setNeedClientAuth(boolean)}, if this option is set and
     * the client chooses not to provide authentication information
     * about itself, <i>the negotiations will continue</i>.
     * <P>
     * Calling this method overrides any previous setting made by
     * this method or {@link #setNeedClientAuth(boolean)}.
     *
     * @param   want set to true if client authentication is requested,
     *          or false if no client authentication is desired.
     * @see     #getWantClientAuth()
     * @see     #setNeedClientAuth(boolean)
     * @see     #getNeedClientAuth()
     * @see     #setUseClientMode(boolean)
     */
    public abstract void setWantClientAuth(boolean want);


    /**
     * Returns true if the engine will <i>request</i> client authentication.
     * This option is only useful for engines in the server mode.
     *
     * @return  true if client authentication is requested,
     *          or false if no client authentication is desired.
     * @see     #setNeedClientAuth(boolean)
     * @see     #getNeedClientAuth()
     * @see     #setWantClientAuth(boolean)
     * @see     #setUseClientMode(boolean)
     */
    public abstract boolean getWantClientAuth();


    /**
     * Controls whether new SSL sessions may be established by this engine.
     * If session creations are not allowed, and there are no
     * existing sessions to resume, there will be no successful
     * handshaking.
     *
     * @param   flag true indicates that sessions may be created; this
     *          is the default.  false indicates that an existing session
     *          must be resumed
     * @see     #getEnableSessionCreation()
     */
    public abstract void setEnableSessionCreation(boolean flag);


    /**
     * Returns true if new SSL sessions may be established by this engine.
     *
     * @return  true indicates that sessions may be created; this
     *          is the default.  false indicates that an existing session
     *          must be resumed
     * @see     #setEnableSessionCreation(boolean)
     */
    public abstract boolean getEnableSessionCreation();

    /**
     * Returns the SSLParameters in effect for this SSLEngine.
     * The ciphersuites and protocols of the returned SSLParameters
     * are always non-null.
     *
     * @return the SSLParameters in effect for this SSLEngine.
     * @since 1.6
     */
    public SSLParameters getSSLParameters() {
        SSLParameters params = new SSLParameters();
        params.setCipherSuites(getEnabledCipherSuites());
        params.setProtocols(getEnabledProtocols());
        if (getNeedClientAuth()) {
            params.setNeedClientAuth(true);
        } else if (getWantClientAuth()) {
            params.setWantClientAuth(true);
        }
        return params;
    }

    /**
     * Applies SSLParameters to this engine.
     *
     * <p>This means:
     * <ul>
     * <li>if <code>params.getCipherSuites()</code> is non-null,
     *   <code>setEnabledCipherSuites()</code> is called with that value
     * <li>if <code>params.getProtocols()</code> is non-null,
     *   <code>setEnabledProtocols()</code> is called with that value
     * <li>if <code>params.getNeedClientAuth()</code> or
     *   <code>params.getWantClientAuth()</code> return <code>true</code>,
     *   <code>setNeedClientAuth(true)</code> and
     *   <code>setWantClientAuth(true)</code> are called, respectively;
     *   otherwise <code>setWantClientAuth(false)</code> is called.
     * </ul>
     *
     * @param params the parameters
     * @throws IllegalArgumentException if the setEnabledCipherSuites() or
     *    the setEnabledProtocols() call fails
     * @since 1.6
     */
    public void setSSLParameters(SSLParameters params) {
        String[] s;
        s = params.getCipherSuites();
        if (s != null) {
            setEnabledCipherSuites(s);
        }
        s = params.getProtocols();
        if (s != null) {
            setEnabledProtocols(s);
        }
        if (params.getNeedClientAuth()) {
            setNeedClientAuth(true);
        } else if (params.getWantClientAuth()) {
            setWantClientAuth(true);
        } else {
            setWantClientAuth(false);
        }
    }

}
