/*
 * Copyright (c) 2003, 2009, 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 sun.security.ssl;

import java.io.*;
import java.nio.*;
import java.nio.ReadOnlyBufferException;
import java.util.LinkedList;
import java.security.*;

import javax.crypto.BadPaddingException;

import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.*;

import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;

/**
 * Implementation of an non-blocking SSLEngine.
 *
 * *Currently*, the SSLEngine code exists in parallel with the current
 * SSLSocket.  As such, the current implementation is using legacy code
 * with many of the same abstractions.  However, it varies in many
 * areas, most dramatically in the IO handling.
 *
 * There are three main I/O threads that can be existing in parallel:
 * wrap(), unwrap(), and beginHandshake().  We are encouraging users to
 * not call multiple instances of wrap or unwrap, because the data could
 * appear to flow out of the SSLEngine in a non-sequential order.  We
 * take all steps we can to at least make sure the ordering remains
 * consistent, but once the calls returns, anything can happen.  For
 * example, thread1 and thread2 both call wrap, thread1 gets the first
 * packet, thread2 gets the second packet, but thread2 gets control back
 * before thread1, and sends the data.  The receiving side would see an
 * out-of-order error.
 *
 * Handshaking is still done the same way as SSLSocket using the normal
 * InputStream/OutputStream abstactions.  We create
 * ClientHandshakers/ServerHandshakers, which produce/consume the
 * handshaking data.  The transfer of the data is largely handled by the
 * HandshakeInStream/HandshakeOutStreams.  Lastly, the
 * InputRecord/OutputRecords still have the same functionality, except
 * that they are overridden with EngineInputRecord/EngineOutputRecord,
 * which provide SSLEngine-specific functionality.
 *
 * Some of the major differences are:
 *
 * EngineInputRecord/EngineOutputRecord/EngineWriter:
 *
 *      In order to avoid writing whole new control flows for
 *      handshaking, and to reuse most of the same code, we kept most
 *      of the actual handshake code the same.  As usual, reading
 *      handshake data may trigger output of more handshake data, so
 *      what we do is write this data to internal buffers, and wait for
 *      wrap() to be called to give that data a ride.
 *
 *      All data is routed through
 *      EngineInputRecord/EngineOutputRecord.  However, all handshake
 *      data (ct_alert/ct_change_cipher_spec/ct_handshake) are passed
 *      through to the the underlying InputRecord/OutputRecord, and
 *      the data uses the internal buffers.
 *
 *      Application data is handled slightly different, we copy the data
 *      directly from the src to the dst buffers, and do all operations
 *      on those buffers, saving the overhead of multiple copies.
 *
 *      In the case of an inbound record, unwrap passes the inbound
 *      ByteBuffer to the InputRecord.  If the data is handshake data,
 *      the data is read into the InputRecord's internal buffer.  If
 *      the data is application data, the data is decoded directly into
 *      the dst buffer.
 *
 *      In the case of an outbound record, when the write to the
 *      "real" OutputStream's would normally take place, instead we
 *      call back up to the EngineOutputRecord's version of
 *      writeBuffer, at which time we capture the resulting output in a
 *      ByteBuffer, and send that back to the EngineWriter for internal
 *      storage.
 *
 *      EngineWriter is responsible for "handling" all outbound
 *      data, be it handshake or app data, and for returning the data
 *      to wrap() in the proper order.
 *
 * ClientHandshaker/ServerHandshaker/Handshaker:
 *      Methods which relied on SSLSocket now have work on either
 *      SSLSockets or SSLEngines.
 *
 * @author Brad Wetmore
 */
final public class SSLEngineImpl extends SSLEngine {

    //
    // Fields and global comments
    //

    /*
     * There's a state machine associated with each connection, which
     * among other roles serves to negotiate session changes.
     *
     * - START with constructor, until the TCP connection's around.
     * - HANDSHAKE picks session parameters before allowing traffic.
     *          There are many substates due to sequencing requirements
     *          for handshake messages.
     * - DATA may be transmitted.
     * - RENEGOTIATE state allows concurrent data and handshaking
     *          traffic ("same" substates as HANDSHAKE), and terminates
     *          in selection of new session (and connection) parameters
     * - ERROR state immediately precedes abortive disconnect.
     * - CLOSED when one side closes down, used to start the shutdown
     *          process.  SSL connection objects are not reused.
     *
     * State affects what SSL record types may legally be sent:
     *
     * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
     * - App Data ... only in DATA and RENEGOTIATE states
     * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
     *
     * Re what may be received:  same as what may be sent, except that
     * HandshakeRequest handshaking messages can come from servers even
     * in the application data state, to request entry to RENEGOTIATE.
     *
     * The state machine within HANDSHAKE and RENEGOTIATE states controls
     * the pending session, not the connection state, until the change
     * cipher spec and "Finished" handshake messages are processed and
     * make the "new" session become the current one.
     *
     * NOTE: details of the SMs always need to be nailed down better.
     * The text above illustrates the core ideas.
     *
     *                +---->-------+------>--------->-------+
     *                |            |                        |
     *     <-----<    ^            ^  <-----<               |
     *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE    |
     *                v            v               v        |
     *                |            |               |        |
     *                +------------+---------------+        |
     *                |                                     |
     *                v                                     |
     *               ERROR>------>----->CLOSED<--------<----+
     *
     * ALSO, note that the the purpose of handshaking (renegotiation is
     * included) is to assign a different, and perhaps new, session to
     * the connection.  The SSLv3 spec is a bit confusing on that new
     * protocol feature.
     */
    private int                 connectionState;

    private static final int    cs_START = 0;
    private static final int    cs_HANDSHAKE = 1;
    private static final int    cs_DATA = 2;
    private static final int    cs_RENEGOTIATE = 3;
    private static final int    cs_ERROR = 4;
    private static final int    cs_CLOSED = 6;

    /*
     * Once we're in state cs_CLOSED, we can continue to
     * wrap/unwrap until we finish sending/receiving the messages
     * for close_notify.  EngineWriter handles outboundDone.
     */
    private boolean             inboundDone = false;

    EngineWriter                writer;

    /*
     * The authentication context holds all information used to establish
     * who this end of the connection is (certificate chains, private keys,
     * etc) and who is trusted (e.g. as CAs or websites).
     */
    private SSLContextImpl      sslContext;

    /*
     * This connection is one of (potentially) many associated with
     * any given session.  The output of the handshake protocol is a
     * new session ... although all the protocol description talks
     * about changing the cipher spec (and it does change), in fact
     * that's incidental since it's done by changing everything that
     * is associated with a session at the same time.  (TLS/IETF may
     * change that to add client authentication w/o new key exchg.)
     */
    private SSLSessionImpl      sess;
    private Handshaker          handshaker;

    /*
     * Client authentication be off, requested, or required.
     *
     * This will be used by both this class and SSLSocket's variants.
     */
    static final byte           clauth_none = 0;
    static final byte           clauth_requested = 1;
    static final byte           clauth_required = 2;

    /*
     * Flag indicating if the next record we receive MUST be a Finished
     * message. Temporarily set during the handshake to ensure that
     * a change cipher spec message is followed by a finished message.
     */
    private boolean             expectingFinished;


    /*
     * If someone tries to closeInbound() (say at End-Of-Stream)
     * our engine having received a close_notify, we need to
     * notify the app that we may have a truncation attack underway.
     */
    private boolean             recvCN;

    /*
     * For improved diagnostics, we detail connection closure
     * If the engine is closed (connectionState >= cs_ERROR),
     * closeReason != null indicates if the engine was closed
     * because of an error or because or normal shutdown.
     */
    private SSLException        closeReason;

    /*
     * Per-connection private state that doesn't change when the
     * session is changed.
     */
    private byte                        doClientAuth;
    private CipherSuiteList             enabledCipherSuites;
    private boolean                     enableSessionCreation = true;
    EngineInputRecord                   inputRecord;
    EngineOutputRecord                  outputRecord;
    private AccessControlContext        acc;

    // hostname identification algorithm, the hostname identification is
    // disabled by default.
    private String                      identificationAlg = null;

    // Have we been told whether we're client or server?
    private boolean                     serverModeSet = false;
    private boolean                     roleIsServer;

    /*
     * The protocols we support are SSL Version 3.0) and
     * TLS (version 3.1).
     * In addition we support a pseudo protocol called
     * SSLv2Hello which when set will result in an SSL v2 Hello
     * being sent with SSLv3 or TLSv1 version info.
     */
    private ProtocolList        enabledProtocols;

    /*
     * The SSL version associated with this connection.
     */
    private ProtocolVersion     protocolVersion = ProtocolVersion.DEFAULT;

    /*
     * Crypto state that's reinitialized when the session changes.
     */
    private MAC                 readMAC, writeMAC;
    private CipherBox           readCipher, writeCipher;
    // NOTE: compression state would be saved here


    /*
     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
     * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
     * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
     *
     * There are several locks here.
     *
     * The primary lock is the per-instance lock used by
     * synchronized(this) and the synchronized methods.  It controls all
     * access to things such as the connection state and variables which
     * affect handshaking.  If we are inside a synchronized method, we
     * can access the state directly, otherwise, we must use the
     * synchronized equivalents.
     *
     * Note that we must never acquire the <code>this</code> lock after
     * <code>writeLock</code> or run the risk of deadlock.
     *
     * Grab some coffee, and be careful with any code changes.
     */
    private Object              wrapLock;
    private Object              unwrapLock;
    Object                      writeLock;

    /*
     * Class and subclass dynamic debugging support
     */
    private static final Debug debug = Debug.getInstance("ssl");

    //
    // Initialization/Constructors
    //

    /**
     * Constructor for an SSLEngine from SSLContext, without
     * host/port hints.  This Engine will not be able to cache
     * sessions, but must renegotiate everything by hand.
     */
    SSLEngineImpl(SSLContextImpl ctx) {
        super();
        init(ctx);
    }

    /**
     * Constructor for an SSLEngine from SSLContext.
     */
    SSLEngineImpl(SSLContextImpl ctx, String host, int port) {
        super(host, port);
        init(ctx);
    }

    /**
     * Initializes the Engine
     */
    private void init(SSLContextImpl ctx) {
        if (debug != null && Debug.isOn("ssl")) {
            System.out.println("Using SSLEngineImpl.");
        }

        sslContext = ctx;
        sess = SSLSessionImpl.nullSession;

        /*
         * State is cs_START until we initialize the handshaker.
         *
         * Apps using SSLEngine are probably going to be server.
         * Somewhat arbitrary choice.
         */
        roleIsServer = true;
        connectionState = cs_START;

        /*
         * default read and write side cipher and MAC support
         *
         * Note:  compression support would go here too
         */
        readCipher = CipherBox.NULL;
        readMAC = MAC.NULL;
        writeCipher = CipherBox.NULL;
        writeMAC = MAC.NULL;

        enabledCipherSuites = CipherSuiteList.getDefault();
        enabledProtocols = ProtocolList.getDefault();

        wrapLock = new Object();
        unwrapLock = new Object();
        writeLock = new Object();

        /*
         * Save the Access Control Context.  This will be used later
         * for a couple of things, including providing a context to
         * run tasks in, and for determining which credentials
         * to use for Subject based (JAAS) decisions
         */
        acc = AccessController.getContext();

        /*
         * All outbound application data goes through this OutputRecord,
         * other data goes through their respective records created
         * elsewhere.  All inbound data goes through this one
         * input record.
         */
        outputRecord =
            new EngineOutputRecord(Record.ct_application_data, this);
        inputRecord = new EngineInputRecord(this);
        inputRecord.enableFormatChecks();

        writer = new EngineWriter();
    }

    /**
     * Initialize the handshaker object. This means:
     *
     *  . if a handshake is already in progress (state is cs_HANDSHAKE
     *    or cs_RENEGOTIATE), do nothing and return
     *
     *  . if the engine is already closed, throw an Exception (internal error)
     *
     *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
     *    object, initialize it, and advance the connection state (to
     *    cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
     *
     * This method is called right after a new engine is created, when
     * starting renegotiation, or when changing client/server mode of the
     * engine.
     */
    private void initHandshaker() {
        switch (connectionState) {

        //
        // Starting a new handshake.
        //
        case cs_START:
        case cs_DATA:
            break;

        //
        // We're already in the middle of a handshake.
        //
        case cs_HANDSHAKE:
        case cs_RENEGOTIATE:
            return;

        //
        // Anyone allowed to call this routine is required to
        // do so ONLY if the connection state is reasonable...
        //
        default:
            throw new IllegalStateException("Internal error");
        }

        // state is either cs_START or cs_DATA
        if (connectionState == cs_START) {
            connectionState = cs_HANDSHAKE;
        } else { // cs_DATA
            connectionState = cs_RENEGOTIATE;
        }
        if (roleIsServer) {
            handshaker = new ServerHandshaker(this, sslContext,
                        enabledProtocols, doClientAuth,
                        connectionState == cs_RENEGOTIATE, protocolVersion);
        } else {
            handshaker = new ClientHandshaker(this, sslContext,
                        enabledProtocols, protocolVersion);
        }
        handshaker.enabledCipherSuites = enabledCipherSuites;
        handshaker.setEnableSessionCreation(enableSessionCreation);
        if (connectionState == cs_RENEGOTIATE) {
            // don't use SSLv2Hello when renegotiating
            handshaker.output.r.setHelloVersion(protocolVersion);
        }
    }

    /*
     * Report the current status of the Handshaker
     */
    private HandshakeStatus getHSStatus(HandshakeStatus hss) {

        if (hss != null) {
            return hss;
        }

        synchronized (this) {
            if (writer.hasOutboundData()) {
                return HandshakeStatus.NEED_WRAP;
            } else if (handshaker != null) {
                if (handshaker.taskOutstanding()) {
                    return HandshakeStatus.NEED_TASK;
                } else {
                    return HandshakeStatus.NEED_UNWRAP;
                }
            } else if (connectionState == cs_CLOSED) {
                /*
                 * Special case where we're closing, but
                 * still need the close_notify before we
                 * can officially be closed.
                 *
                 * Note isOutboundDone is taken care of by
                 * hasOutboundData() above.
                 */
                if (!isInboundDone()) {
                    return HandshakeStatus.NEED_UNWRAP;
                } // else not handshaking
            }

            return HandshakeStatus.NOT_HANDSHAKING;
        }
    }

    synchronized private void checkTaskThrown() throws SSLException {
        if (handshaker != null) {
            handshaker.checkThrown();
        }
    }

    //
    // Handshaking and connection state code
    //

    /*
     * Provides "this" synchronization for connection state.
     * Otherwise, you can access it directly.
     */
    synchronized private int getConnectionState() {
        return connectionState;
    }

    synchronized private void setConnectionState(int state) {
        connectionState = state;
    }

    /*
     * Get the Access Control Context.
     *
     * Used for a known context to
     * run tasks in, and for determining which credentials
     * to use for Subject-based (JAAS) decisions.
     */
    AccessControlContext getAcc() {
        return acc;
    }

    /*
     * Is a handshake currently underway?
     */
    public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
        return getHSStatus(null);
    }

    /*
     * When a connection finishes handshaking by enabling use of a newly
     * negotiated session, each end learns about it in two halves (read,
     * and write).  When both read and write ciphers have changed, and the
     * last handshake message has been read, the connection has joined
     * (rejoined) the new session.
     *
     * NOTE:  The SSLv3 spec is rather unclear on the concepts here.
     * Sessions don't change once they're established (including cipher
     * suite and master secret) but connections can join them (and leave
     * them).  They're created by handshaking, though sometime handshaking
     * causes connections to join up with pre-established sessions.
     *
     * Synchronized on "this" from readRecord.
     */
    private void changeReadCiphers() throws SSLException {
        if (connectionState != cs_HANDSHAKE
                && connectionState != cs_RENEGOTIATE) {
            throw new SSLProtocolException(
                "State error, change cipher specs");
        }

        // ... create decompressor

        CipherBox oldCipher = readCipher;

        try {
            readCipher = handshaker.newReadCipher();
            readMAC = handshaker.newReadMAC();
        } catch (GeneralSecurityException e) {
            // "can't happen"
            throw (SSLException)new SSLException
                                ("Algorithm missing:  ").initCause(e);
        }

        /*
         * Dispose of any intermediate state in the underlying cipher.
         * For PKCS11 ciphers, this will release any attached sessions,
         * and thus make finalization faster.
         *
         * Since MAC's doFinal() is called for every SSL/TLS packet, it's
         * not necessary to do the same with MAC's.
         */
        oldCipher.dispose();
    }

    /*
     * used by Handshaker to change the active write cipher, follows
     * the output of the CCS message.
     *
     * Also synchronized on "this" from readRecord/delegatedTask.
     */
    void changeWriteCiphers() throws SSLException {
        if (connectionState != cs_HANDSHAKE
                && connectionState != cs_RENEGOTIATE) {
            throw new SSLProtocolException(
                "State error, change cipher specs");
        }

        // ... create compressor

        CipherBox oldCipher = writeCipher;

        try {
            writeCipher = handshaker.newWriteCipher();
            writeMAC = handshaker.newWriteMAC();
        } catch (GeneralSecurityException e) {
            // "can't happen"
            throw (SSLException)new SSLException
                                ("Algorithm missing:  ").initCause(e);
        }

        // See comment above.
        oldCipher.dispose();
    }

    /*
     * Updates the SSL version associated with this connection.
     * Called from Handshaker once it has determined the negotiated version.
     */
    synchronized void setVersion(ProtocolVersion protocolVersion) {
        this.protocolVersion = protocolVersion;
        outputRecord.setVersion(protocolVersion);
    }


    /**
     * Kickstart the handshake if it is not already in progress.
     * This means:
     *
     *  . if handshaking is already underway, do nothing and return
     *
     *  . if the engine is not connected or already closed, throw an
     *    Exception.
     *
     *  . otherwise, call initHandshake() to initialize the handshaker
     *    object and progress the state. Then, send the initial
     *    handshaking message if appropriate (always on clients and
     *    on servers when renegotiating).
     */
    private synchronized void kickstartHandshake() throws IOException {
        switch (connectionState) {

        case cs_START:
            if (!serverModeSet) {
                throw new IllegalStateException(
                    "Client/Server mode not yet set.");
            }
            initHandshaker();
            break;

        case cs_HANDSHAKE:
            // handshaker already setup, proceed
            break;

        case cs_DATA:
            if (!Handshaker.renegotiable) {
                throw new SSLHandshakeException("renegotiation is not allowed");
            }

            // initialize the handshaker, move to cs_RENEGOTIATE
            initHandshaker();
            break;

        case cs_RENEGOTIATE:
            // handshaking already in progress, return
            return;

        default:
            // cs_ERROR/cs_CLOSED
            throw new SSLException("SSLEngine is closing/closed");
        }

        //
        // Kickstart handshake state machine if we need to ...
        //
        // Note that handshaker.kickstart() writes the message
        // to its HandshakeOutStream, which calls back into
        // SSLSocketImpl.writeRecord() to send it.
        //
        if (!handshaker.started()) {
            if (handshaker instanceof ClientHandshaker) {
                // send client hello
                handshaker.kickstart();
            } else {    // instanceof ServerHandshaker
                if (connectionState == cs_HANDSHAKE) {
                    // initial handshake, no kickstart message to send
                } else {
                    // we want to renegotiate, send hello request
                    handshaker.kickstart();
                    // hello request is not included in the handshake
                    // hashes, reset them
                    handshaker.handshakeHash.reset();
                }
            }
        }
    }

    /*
     * Start a SSLEngine handshake
     */
    public void beginHandshake() throws SSLException {
        try {
            kickstartHandshake();
        } catch (Exception e) {
            fatal(Alerts.alert_handshake_failure,
                "Couldn't kickstart handshaking", e);
        }
    }


    //
    // Read/unwrap side
    //


    /**
     * Unwraps a buffer.  Does a variety of checks before grabbing
     * the unwrapLock, which blocks multiple unwraps from occuring.
     */
    public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData,
            int offset, int length) throws SSLException {

        EngineArgs ea = new EngineArgs(netData, appData, offset, length);

        try {
            synchronized (unwrapLock) {
                return readNetRecord(ea);
            }
        } catch (Exception e) {
            /*
             * Don't reset position so it looks like we didn't
             * consume anything.  We did consume something, and it
             * got us into this situation, so report that much back.
             * Our days of consuming are now over anyway.
             */
            fatal(Alerts.alert_internal_error,
                "problem unwrapping net record", e);
            return null;  // make compiler happy
        } finally {
            /*
             * Just in case something failed to reset limits properly.
             */
            ea.resetLim();
        }
    }

    /*
     * Makes additional checks for unwrap, but this time more
     * specific to this packet and the current state of the machine.
     */
    private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException {

        Status status = null;
        HandshakeStatus hsStatus = null;

        /*
         * See if the handshaker needs to report back some SSLException.
         */
        checkTaskThrown();

        /*
         * Check if we are closing/closed.
         */
        if (isInboundDone()) {
            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
        }

        /*
         * If we're still in cs_HANDSHAKE, make sure it's been
         * started.
         */
        synchronized (this) {
            if ((connectionState == cs_HANDSHAKE) ||
                    (connectionState == cs_START)) {
                kickstartHandshake();

                /*
                 * If there's still outbound data to flush, we
                 * can return without trying to unwrap anything.
                 */
                hsStatus = getHSStatus(null);

                if (hsStatus == HandshakeStatus.NEED_WRAP) {
                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
                }
            }
        }

        /*
         * Grab a copy of this if it doesn't already exist,
         * and we can use it several places before anything major
         * happens on this side.  Races aren't critical
         * here.
         */
        if (hsStatus == null) {
            hsStatus = getHSStatus(null);
        }

        /*
         * If we have a task outstanding, this *MUST* be done before
         * doing any more unwrapping, because we could be in the middle
         * of receiving a handshake message, for example, a finished
         * message which would change the ciphers.
         */
        if (hsStatus == HandshakeStatus.NEED_TASK) {
            return new SSLEngineResult(
                Status.OK, hsStatus, 0, 0);
        }

        /*
         * Check the packet to make sure enough is here.
         * This will also indirectly check for 0 len packets.
         */
        int packetLen = inputRecord.bytesInCompletePacket(ea.netData);

        // Is this packet bigger than SSL/TLS normally allows?
        if (packetLen > sess.getPacketBufferSize()) {
            if (packetLen > Record.maxLargeRecordSize) {
                throw new SSLProtocolException(
                    "Input SSL/TLS record too big: max = " +
                    Record.maxLargeRecordSize +
                    " len = " + packetLen);
            } else {
                // Expand the expected maximum packet/application buffer
                // sizes.
                sess.expandBufferSizes();
            }
        }

        /*
         * Check for OVERFLOW.
         *
         * To be considered: We could delay enforcing the application buffer
         * free space requirement until after the initial handshaking.
         */
        if ((packetLen - Record.headerSize) > ea.getAppRemaining()) {
            return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
        }

        // check for UNDERFLOW.
        if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) {
            return new SSLEngineResult(
                Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
        }

        /*
         * We're now ready to actually do the read.
         * The only result code we really need to be exactly
         * right is the HS finished, for signaling to
         * HandshakeCompletedListeners.
         */
        try {
            hsStatus = readRecord(ea);
        } catch (SSLException e) {
            throw e;
        } catch (IOException e) {
            SSLException ex = new SSLException("readRecord");
            ex.initCause(e);
            throw ex;
        }

        /*
         * Check the various condition that we could be reporting.
         *
         * It's *possible* something might have happened between the
         * above and now, but it was better to minimally lock "this"
         * during the read process.  We'll return the current
         * status, which is more representative of the current state.
         *
         * status above should cover:  FINISHED, NEED_TASK
         */
        status = (isInboundDone() ? Status.CLOSED : Status.OK);
        hsStatus = getHSStatus(hsStatus);

        return new SSLEngineResult(status, hsStatus,
            ea.deltaNet(), ea.deltaApp());
    }

    /*
     * Actually do the read record processing.
     *
     * Returns a Status if it can make specific determinations
     * of the engine state.  In particular, we need to signal
     * that a handshake just completed.
     *
     * It would be nice to be symmetrical with the write side and move
     * the majority of this to EngineInputRecord, but there's too much
     * SSLEngine state to do that cleanly.  It must still live here.
     */
    private HandshakeStatus readRecord(EngineArgs ea) throws IOException {

        HandshakeStatus hsStatus = null;

        /*
         * The various operations will return new sliced BB's,
         * this will avoid having to worry about positions and
         * limits in the netBB.
         */
        ByteBuffer readBB = null;
        ByteBuffer decryptedBB = null;

        if (getConnectionState() != cs_ERROR) {

            /*
             * Read a record ... maybe emitting an alert if we get a
             * comprehensible but unsupported "hello" message during
             * format checking (e.g. V2).
             */
            try {
                readBB = inputRecord.read(ea.netData);
            } catch (IOException e) {
                fatal(Alerts.alert_unexpected_message, e);
            }

            /*
             * The basic SSLv3 record protection involves (optional)
             * encryption for privacy, and an integrity check ensuring
             * data origin authentication.  We do them both here, and
             * throw a fatal alert if the integrity check fails.
             */
            try {
                decryptedBB = inputRecord.decrypt(readCipher, readBB);
            } catch (BadPaddingException e) {
                // RFC 2246 states that decryption_failed should be used
                // for this purpose. However, that allows certain attacks,
                // so we just send bad record MAC. We also need to make
                // sure to always check the MAC to avoid a timing attack
                // for the same issue. See paper by Vaudenay et al.
                //
                // rewind the BB if necessary.
                readBB.rewind();

                inputRecord.checkMAC(readMAC, readBB);

                // use the same alert types as for MAC failure below
                byte alertType = (inputRecord.contentType() ==
                    Record.ct_handshake) ?
                        Alerts.alert_handshake_failure :
                        Alerts.alert_bad_record_mac;
                fatal(alertType, "Invalid padding", e);
            }

            if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
                if (inputRecord.contentType() == Record.ct_handshake) {
                    fatal(Alerts.alert_handshake_failure,
                        "bad handshake record MAC");
                } else {
                    fatal(Alerts.alert_bad_record_mac, "bad record MAC");
                }
            }

            // if (!inputRecord.decompress(c))
            //     fatal(Alerts.alert_decompression_failure,
            //     "decompression failure");


            /*
             * Process the record.
             */

            synchronized (this) {
                switch (inputRecord.contentType()) {
                case Record.ct_handshake:
                    /*
                     * Handshake messages always go to a pending session
                     * handshaker ... if there isn't one, create one.  This
                     * must work asynchronously, for renegotiation.
                     *
                     * NOTE that handshaking will either resume a session
                     * which was in the cache (and which might have other
                     * connections in it already), or else will start a new
                     * session (new keys exchanged) with just this connection
                     * in it.
                     */
                    initHandshaker();

                    /*
                     * process the handshake record ... may contain just
                     * a partial handshake message or multiple messages.
                     *
                     * The handshaker state machine will ensure that it's
                     * a finished message.
                     */
                    handshaker.process_record(inputRecord, expectingFinished);
                    expectingFinished = false;

                    if (handshaker.invalidated) {
                        handshaker = null;
                        // if state is cs_RENEGOTIATE, revert it to cs_DATA
                        if (connectionState == cs_RENEGOTIATE) {
                            connectionState = cs_DATA;
                        }
                    } else if (handshaker.isDone()) {
                        sess = handshaker.getSession();
                        if (!writer.hasOutboundData()) {
                            hsStatus = HandshakeStatus.FINISHED;
                        }
                        handshaker = null;
                        connectionState = cs_DATA;

                        // No handshakeListeners here.  That's a
                        // SSLSocket thing.
                    } else if (handshaker.taskOutstanding()) {
                        hsStatus = HandshakeStatus.NEED_TASK;
                    }
                    break;

                case Record.ct_application_data:
                    // Pass this right back up to the application.
                    if ((connectionState != cs_DATA)
                            && (connectionState != cs_RENEGOTIATE)
                            && (connectionState != cs_CLOSED)) {
                        throw new SSLProtocolException(
                            "Data received in non-data state: " +
                            connectionState);
                    }

                    if (expectingFinished) {
                        throw new SSLProtocolException
                                ("Expecting finished message, received data");
                    }

                    /*
                     * Don't return data once the inbound side is
                     * closed.
                     */
                    if (!inboundDone) {
                        ea.scatter(decryptedBB.slice());
                    }
                    break;

                case Record.ct_alert:
                    recvAlert();
                    break;

                case Record.ct_change_cipher_spec:
                    if ((connectionState != cs_HANDSHAKE
                                && connectionState != cs_RENEGOTIATE)
                            || inputRecord.available() != 1
                            || inputRecord.read() != 1) {
                        fatal(Alerts.alert_unexpected_message,
                            "illegal change cipher spec msg, state = "
                            + connectionState);
                    }

                    //
                    // The first message after a change_cipher_spec
                    // record MUST be a "Finished" handshake record,
                    // else it's a protocol violation.  We force this
                    // to be checked by a minor tweak to the state
                    // machine.
                    //
                    changeReadCiphers();
                    // next message MUST be a finished message
                    expectingFinished = true;
                    break;

                default:
                    //
                    // TLS requires that unrecognized records be ignored.
                    //
                    if (debug != null && Debug.isOn("ssl")) {
                        System.out.println(threadName() +
                            ", Received record type: "
                            + inputRecord.contentType());
                    }
                    break;
                } // switch
            } // synchronized (this)
        }

        return hsStatus;
    }


    //
    // write/wrap side
    //


    /**
     * Wraps a buffer.  Does a variety of checks before grabbing
     * the wrapLock, which blocks multiple wraps from occuring.
     */
    public SSLEngineResult wrap(ByteBuffer [] appData,
            int offset, int length, ByteBuffer netData) throws SSLException {

        EngineArgs ea = new EngineArgs(appData, offset, length, netData);

        /*
         * We can be smarter about using smaller buffer sizes later.
         * For now, force it to be large enough to handle any
         * valid SSL/TLS record.
         */
        if (netData.remaining() < outputRecord.maxRecordSize) {
            return new SSLEngineResult(
                Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
        }

        try {
            synchronized (wrapLock) {
                return writeAppRecord(ea);
            }
        } catch (Exception e) {
            ea.resetPos();

            fatal(Alerts.alert_internal_error,
                "problem unwrapping net record", e);
            return null;  // make compiler happy
        } finally {
            /*
             * Just in case something didn't reset limits properly.
             */
            ea.resetLim();
        }
    }

    /*
     * Makes additional checks for unwrap, but this time more
     * specific to this packet and the current state of the machine.
     */
    private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {

        Status status = null;
        HandshakeStatus hsStatus = null;

        /*
         * See if the handshaker needs to report back some SSLException.
         */
        checkTaskThrown();

        /*
         * short circuit if we're closed/closing.
         */
        if (writer.isOutboundDone()) {
            return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
        }

        /*
         * If we're still in cs_HANDSHAKE, make sure it's been
         * started.
         */
        synchronized (this) {
            if ((connectionState == cs_HANDSHAKE) ||
                    (connectionState == cs_START)) {
                kickstartHandshake();

                /*
                 * If there's no HS data available to write, we can return
                 * without trying to wrap anything.
                 */
                hsStatus = getHSStatus(null);

                if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
                    return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
                }
            }
        }

        /*
         * Grab a copy of this if it doesn't already exist,
         * and we can use it several places before anything major
         * happens on this side.  Races aren't critical
         * here.
         */
        if (hsStatus == null) {
            hsStatus = getHSStatus(null);
        }

        /*
         * If we have a task outstanding, this *MUST* be done before
         * doing any more wrapping, because we could be in the middle
         * of receiving a handshake message, for example, a finished
         * message which would change the ciphers.
         */
        if (hsStatus == HandshakeStatus.NEED_TASK) {
            return new SSLEngineResult(
                Status.OK, hsStatus, 0, 0);
        }

        /*
         * This will obtain any waiting outbound data, or will
         * process the outbound appData.
         */
        try {
            synchronized (writeLock) {
                hsStatus = writeRecord(outputRecord, ea);
            }
        } catch (SSLException e) {
            throw e;
        } catch (IOException e) {
            SSLException ex = new SSLException("Write problems");
            ex.initCause(e);
            throw ex;
        }

        /*
         * writeRecord might have reported some status.
         * Now check for the remaining cases.
         *
         * status above should cover:  NEED_WRAP/FINISHED
         */
        status = (isOutboundDone() ? Status.CLOSED : Status.OK);
        hsStatus = getHSStatus(hsStatus);

        return new SSLEngineResult(status, hsStatus,
            ea.deltaApp(), ea.deltaNet());
    }

    /*
     * Central point to write/get all of the outgoing data.
     */
    private HandshakeStatus writeRecord(EngineOutputRecord eor,
            EngineArgs ea) throws IOException {

        // eventually compress as well.
        return writer.writeRecord(eor, ea, writeMAC, writeCipher);
    }

    /*
     * Non-application OutputRecords go through here.
     */
    void writeRecord(EngineOutputRecord eor) throws IOException {
        // eventually compress as well.
        writer.writeRecord(eor, writeMAC, writeCipher);
    }

    //
    // Close code
    //

    /**
     * Signals that no more outbound application data will be sent
     * on this <code>SSLEngine</code>.
     */
    private void closeOutboundInternal() {

        if ((debug != null) && Debug.isOn("ssl")) {
            System.out.println(threadName() + ", closeOutboundInternal()");
        }

        /*
         * Already closed, ignore
         */
        if (writer.isOutboundDone()) {
            return;
        }

        switch (connectionState) {

        /*
         * If we haven't even started yet, don't bother reading inbound.
         */
        case cs_START:
            writer.closeOutbound();
            inboundDone = true;
            break;

        case cs_ERROR:
        case cs_CLOSED:
            break;

        /*
         * Otherwise we indicate clean termination.
         */
        // case cs_HANDSHAKE:
        // case cs_DATA:
        // case cs_RENEGOTIATE:
        default:
            warning(Alerts.alert_close_notify);
            writer.closeOutbound();
            break;
        }

        // See comment in changeReadCiphers()
        writeCipher.dispose();

        connectionState = cs_CLOSED;
    }

    synchronized public void closeOutbound() {
        /*
         * Dump out a close_notify to the remote side
         */
        if ((debug != null) && Debug.isOn("ssl")) {
            System.out.println(threadName() + ", called closeOutbound()");
        }

        closeOutboundInternal();
    }

    /**
     * Returns the outbound application data closure state
     */
    public boolean isOutboundDone() {
        return writer.isOutboundDone();
    }

    /**
     * Signals that no more inbound network data will be sent
     * to this <code>SSLEngine</code>.
     */
    private void closeInboundInternal() {

        if ((debug != null) && Debug.isOn("ssl")) {
            System.out.println(threadName() + ", closeInboundInternal()");
        }

        /*
         * Already closed, ignore
         */
        if (inboundDone) {
            return;
        }

        closeOutboundInternal();
        inboundDone = true;

        // See comment in changeReadCiphers()
        readCipher.dispose();

        connectionState = cs_CLOSED;
    }

    /*
     * Close the inbound side of the connection.  We grab the
     * lock here, and do the real work in the internal verison.
     * We do check for truncation attacks.
     */
    synchronized public void closeInbound() throws SSLException {
        /*
         * Currently closes the outbound side as well.  The IETF TLS
         * working group has expressed the opinion that 1/2 open
         * connections are not allowed by the spec.  May change
         * someday in the future.
         */
        if ((debug != null) && Debug.isOn("ssl")) {
            System.out.println(threadName() + ", called closeInbound()");
        }

        /*
         * No need to throw an Exception if we haven't even started yet.
         */
        if ((connectionState != cs_START) && !recvCN) {
            recvCN = true;  // Only receive the Exception once
            fatal(Alerts.alert_internal_error,
                "Inbound closed before receiving peer's close_notify: " +
                "possible truncation attack?");
        } else {
            /*
             * Currently, this is a no-op, but in case we change
             * the close inbound code later.
             */
            closeInboundInternal();
        }
    }

    /**
     * Returns the network inbound data closure state
     */
    synchronized public boolean isInboundDone() {
        return inboundDone;
    }


    //
    // Misc stuff
    //


    /**
     * Returns the current <code>SSLSession</code> for this
     * <code>SSLEngine</code>
     * <P>
     * These can be long lived, and frequently correspond to an
     * entire login session for some user.
     */
    synchronized public SSLSession getSession() {
        return sess;
    }

    /**
     * Returns a delegated <code>Runnable</code> task for
     * this <code>SSLEngine</code>.
     */
    synchronized public Runnable getDelegatedTask() {
        if (handshaker != null) {
            return handshaker.getTask();
        }
        return null;
    }


    //
    // EXCEPTION AND ALERT HANDLING
    //

    /*
     * Send a warning alert.
     */
    void warning(byte description) {
        sendAlert(Alerts.alert_warning, description);
    }

    synchronized void fatal(byte description, String diagnostic)
            throws SSLException {
        fatal(description, diagnostic, null);
    }

    synchronized void fatal(byte description, Throwable cause)
            throws SSLException {
        fatal(description, null, cause);
    }

    /*
     * We've got a fatal error here, so start the shutdown process.
     *
     * Because of the way the code was written, we have some code
     * calling fatal directly when the "description" is known
     * and some throwing Exceptions which are then caught by higher
     * levels which then call here.  This code needs to determine
     * if one of the lower levels has already started the process.
     *
     * We won't worry about Error's, if we have one of those,
     * we're in worse trouble.  Note:  the networking code doesn't
     * deal with Errors either.
     */
    synchronized void fatal(byte description, String diagnostic,
            Throwable cause) throws SSLException {

        /*
         * If we have no further information, make a general-purpose
         * message for folks to see.  We generally have one or the other.
         */
        if (diagnostic == null) {
            diagnostic = "General SSLEngine problem";
        }
        if (cause == null) {
            cause = Alerts.getSSLException(description, cause, diagnostic);
        }

        /*
         * If we've already shutdown because of an error,
         * there is nothing we can do except rethrow the exception.
         *
         * Most exceptions seen here will be SSLExceptions.
         * We may find the occasional Exception which hasn't been
         * converted to a SSLException, so we'll do it here.
         */
        if (closeReason != null) {
            if ((debug != null) && Debug.isOn("ssl")) {
                System.out.println(threadName() +
                    ", fatal: engine already closed.  Rethrowing " +
                    cause.toString());
            }
            if (cause instanceof RuntimeException) {
                throw (RuntimeException)cause;
            } else if (cause instanceof SSLException) {
                throw (SSLException)cause;
            } else if (cause instanceof Exception) {
                SSLException ssle = new SSLException(
                    "fatal SSLEngine condition");
                ssle.initCause(cause);
                throw ssle;
            }
        }

        if ((debug != null) && Debug.isOn("ssl")) {
            System.out.println(threadName()
                        + ", fatal error: " + description +
                        ": " + diagnostic + "\n" + cause.toString());
        }

        /*
         * Ok, this engine's going down.
         */
        int oldState = connectionState;
        connectionState = cs_ERROR;

        inboundDone = true;

        sess.invalidate();

        /*
         * If we haven't even started handshaking yet, no need
         * to generate the fatal close alert.
         */
        if (oldState != cs_START) {
            sendAlert(Alerts.alert_fatal, description);
        }

        if (cause instanceof SSLException) { // only true if != null
            closeReason = (SSLException)cause;
        } else {
            /*
             * Including RuntimeExceptions, but we'll throw those
             * down below.  The closeReason isn't used again,
             * except for null checks.
             */
            closeReason =
                Alerts.getSSLException(description, cause, diagnostic);
        }

        writer.closeOutbound();

        connectionState = cs_CLOSED;

        // See comment in changeReadCiphers()
        readCipher.dispose();
        writeCipher.dispose();

        if (cause instanceof RuntimeException) {
            throw (RuntimeException)cause;
        } else {
            throw closeReason;
        }
    }

    /*
     * Process an incoming alert ... caller must already have synchronized
     * access to "this".
     */
    private void recvAlert() throws IOException {
        byte level = (byte)inputRecord.read();
        byte description = (byte)inputRecord.read();
        if (description == -1) { // check for short message
            fatal(Alerts.alert_illegal_parameter, "Short alert message");
        }

        if (debug != null && (Debug.isOn("record") ||
                Debug.isOn("handshake"))) {
            synchronized (System.out) {
                System.out.print(threadName());
                System.out.print(", RECV " + protocolVersion + " ALERT:  ");
                if (level == Alerts.alert_fatal) {
                    System.out.print("fatal, ");
                } else if (level == Alerts.alert_warning) {
                    System.out.print("warning, ");
                } else {
                    System.out.print("<level " + (0x0ff & level) + ">, ");
                }
                System.out.println(Alerts.alertDescription(description));
            }
        }

        if (level == Alerts.alert_warning) {
            if (description == Alerts.alert_close_notify) {
                if (connectionState == cs_HANDSHAKE) {
                    fatal(Alerts.alert_unexpected_message,
                                "Received close_notify during handshake");
                } else {
                    recvCN = true;
                    closeInboundInternal();  // reply to close
                }
            } else {

                //
                // The other legal warnings relate to certificates,
                // e.g. no_certificate, bad_certificate, etc; these
                // are important to the handshaking code, which can
                // also handle illegal protocol alerts if needed.
                //
                if (handshaker != null) {
                    handshaker.handshakeAlert(description);
                }
            }
        } else { // fatal or unknown level
            String reason = "Received fatal alert: "
                + Alerts.alertDescription(description);
            if (closeReason == null) {
                closeReason = Alerts.getSSLException(description, reason);
            }
            fatal(Alerts.alert_unexpected_message, reason);
        }
    }


    /*
     * Emit alerts.  Caller must have synchronized with "this".
     */
    private void sendAlert(byte level, byte description) {
        if (connectionState >= cs_CLOSED) {
            return;
        }

        EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
        r.setVersion(protocolVersion);

        boolean useDebug = debug != null && Debug.isOn("ssl");
        if (useDebug) {
            synchronized (System.out) {
                System.out.print(threadName());
                System.out.print(", SEND " + protocolVersion + " ALERT:  ");
                if (level == Alerts.alert_fatal) {
                    System.out.print("fatal, ");
                } else if (level == Alerts.alert_warning) {
                    System.out.print("warning, ");
                } else {
                    System.out.print("<level = " + (0x0ff & level) + ">, ");
                }
                System.out.println("description = "
                        + Alerts.alertDescription(description));
            }
        }

        r.write(level);
        r.write(description);
        try {
            writeRecord(r);
        } catch (IOException e) {
            if (useDebug) {
                System.out.println(threadName() +
                    ", Exception sending alert: " + e);
            }
        }
    }


    //
    // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
    //


    /**
     * Controls whether new connections may cause creation of new SSL
     * sessions.
     *
     * As long as handshaking has not started, we can change
     * whether we enable session creations.  Otherwise,
     * we will need to wait for the next handshake.
     */
    synchronized public void setEnableSessionCreation(boolean flag) {
        enableSessionCreation = flag;

        if ((handshaker != null) && !handshaker.started()) {
            handshaker.setEnableSessionCreation(enableSessionCreation);
        }
    }

    /**
     * Returns true if new connections may cause creation of new SSL
     * sessions.
     */
    synchronized public boolean getEnableSessionCreation() {
        return enableSessionCreation;
    }


    /**
     * Sets the flag controlling whether a server mode engine
     * *REQUIRES* SSL client authentication.
     *
     * As long as handshaking has not started, we can change
     * whether client authentication is needed.  Otherwise,
     * we will need to wait for the next handshake.
     */
    synchronized public void setNeedClientAuth(boolean flag) {
        doClientAuth = (flag ?
            SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);

        if ((handshaker != null) &&
                (handshaker instanceof ServerHandshaker) &&
                !handshaker.started()) {
            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
        }
    }

    synchronized public boolean getNeedClientAuth() {
        return (doClientAuth == SSLEngineImpl.clauth_required);
    }

    /**
     * Sets the flag controlling whether a server mode engine
     * *REQUESTS* SSL client authentication.
     *
     * As long as handshaking has not started, we can change
     * whether client authentication is requested.  Otherwise,
     * we will need to wait for the next handshake.
     */
    synchronized public void setWantClientAuth(boolean flag) {
        doClientAuth = (flag ?
            SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);

        if ((handshaker != null) &&
                (handshaker instanceof ServerHandshaker) &&
                !handshaker.started()) {
            ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
        }
    }

    synchronized public boolean getWantClientAuth() {
        return (doClientAuth == SSLEngineImpl.clauth_requested);
    }


    /**
     * Sets the flag controlling whether the engine is in SSL
     * client or server mode.  Must be called before any SSL
     * traffic has started.
     */
    synchronized public void setUseClientMode(boolean flag) {
        switch (connectionState) {

        case cs_START:
            roleIsServer = !flag;
            serverModeSet = true;
            break;

        case cs_HANDSHAKE:
            /*
             * If we have a handshaker, but haven't started
             * SSL traffic, we can throw away our current
             * handshaker, and start from scratch.  Don't
             * need to call doneConnect() again, we already
             * have the streams.
             */
            assert(handshaker != null);
            if (!handshaker.started()) {
                roleIsServer = !flag;
                connectionState = cs_START;
                initHandshaker();
                break;
            }

            // If handshake has started, that's an error.  Fall through...

        default:
            if (debug != null && Debug.isOn("ssl")) {
                System.out.println(threadName() +
                    ", setUseClientMode() invoked in state = " +
                    connectionState);
            }

            /*
             * We can let them continue if they catch this correctly,
             * we don't need to shut this down.
             */
            throw new IllegalArgumentException(
                "Cannot change mode after SSL traffic has started");
        }
    }

    synchronized public boolean getUseClientMode() {
        return !roleIsServer;
    }


    /**
     * Returns the names of the cipher suites which could be enabled for use
     * on an SSL connection.  Normally, only a subset of these will actually
     * be enabled by default, since this list may include cipher suites which
     * do not support the mutual authentication of servers and clients, or
     * which do not protect data confidentiality.  Servers may also need
     * certain kinds of certificates to use certain cipher suites.
     *
     * @return an array of cipher suite names
     */
    public String[] getSupportedCipherSuites() {
        CipherSuiteList.clearAvailableCache();
        return CipherSuiteList.getSupported().toStringArray();
    }

    /**
     * Controls which particular cipher suites are enabled for use on
     * this connection.  The cipher suites must have been listed by
     * getCipherSuites() as being supported.  Even if a suite has been
     * enabled, it might never be used if no peer supports it or the
     * requisite certificates (and private keys) are not available.
     *
     * @param suites Names of all the cipher suites to enable.
     */
    synchronized public void setEnabledCipherSuites(String[] suites) {
        enabledCipherSuites = new CipherSuiteList(suites);
        if ((handshaker != null) && !handshaker.started()) {
            handshaker.enabledCipherSuites = enabledCipherSuites;
        }
    }

    /**
     * Returns the names of the SSL cipher suites which are currently enabled
     * for use on this connection.  When an SSL engine is first created,
     * all enabled cipher suites <em>(a)</em> protect data confidentiality,
     * by traffic encryption, and <em>(b)</em> can mutually authenticate
     * both clients and servers.  Thus, in some environments, this value
     * might be empty.
     *
     * @return an array of cipher suite names
     */
    synchronized public String[] getEnabledCipherSuites() {
        return enabledCipherSuites.toStringArray();
    }


    /**
     * Returns the protocols that are supported by this implementation.
     * A subset of the supported protocols may be enabled for this connection
     * @ returns an array of protocol names.
     */
    public String[] getSupportedProtocols() {
        return ProtocolList.getSupported().toStringArray();
    }

    /**
     * Controls which protocols are enabled for use on
     * this connection.  The protocols must have been listed by
     * getSupportedProtocols() as being supported.
     *
     * @param protocols protocols to enable.
     * @exception IllegalArgumentException when one of the protocols
     *  named by the parameter is not supported.
     */
    synchronized public void setEnabledProtocols(String[] protocols) {
        enabledProtocols = new ProtocolList(protocols);
        if ((handshaker != null) && !handshaker.started()) {
            handshaker.setEnabledProtocols(enabledProtocols);
        }
    }

    synchronized public String[] getEnabledProtocols() {
        return enabledProtocols.toStringArray();
    }

    /**
     * Try to configure the endpoint identification algorithm of the engine.
     *
     * @param identificationAlgorithm the algorithm used to check the
     *          endpoint identity.
     * @return true if the identification algorithm configuration success.
     */
    synchronized public boolean trySetHostnameVerification(
        String identificationAlgorithm) {
        if (sslContext.getX509TrustManager() instanceof
                X509ExtendedTrustManager) {
            this.identificationAlg = identificationAlgorithm;
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns the endpoint identification algorithm of the engine.
     */
    synchronized public String getHostnameVerification() {
        return identificationAlg;
    }

    /**
     * Return the name of the current thread. Utility method.
     */
    private static String threadName() {
        return Thread.currentThread().getName();
    }

    /**
     * Returns a printable representation of this end of the connection.
     */
    public String toString() {
        StringBuilder retval = new StringBuilder(80);

        retval.append(Integer.toHexString(hashCode()));
        retval.append("[");
        retval.append("SSLEngine[hostname=");
        String host = getPeerHost();
        retval.append((host == null) ? "null" : host);
        retval.append(" port=");
        retval.append(Integer.toString(getPeerPort()));
        retval.append("] ");
        retval.append(getSession().getCipherSuite());
        retval.append("]");

        return retval.toString();
    }
}
