/* | 
|
 * Copyright (c) 2003, 2017, 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;  | 
|
/**  | 
|
* An encapsulation of the result state produced by  | 
|
 * {@code SSLEngine} I/O calls. | 
|
*  | 
|
 * <p> A {@code SSLEngine} provides a means for establishing | 
|
 * secure communication sessions between two peers.  {@code SSLEngine} | 
|
* operations typically consume bytes from an input buffer and produce  | 
|
* bytes in an output buffer. This class provides operational result  | 
|
 * values describing the state of the {@code SSLEngine}, including | 
|
* indications of what operations are needed to finish an  | 
|
* ongoing handshake. Lastly, it reports the number of bytes consumed  | 
|
* and produced as a result of this operation.  | 
|
*  | 
|
* @see SSLEngine  | 
|
* @see SSLEngine#wrap(ByteBuffer, ByteBuffer)  | 
|
* @see SSLEngine#unwrap(ByteBuffer, ByteBuffer)  | 
|
*  | 
|
* @author Brad R. Wetmore  | 
|
* @since 1.5  | 
|
*/  | 
|
public class SSLEngineResult { | 
|
    /** | 
|
     * An {@code SSLEngineResult} enum describing the overall result | 
|
     * of the {@code SSLEngine} operation. | 
|
     * | 
|
     * The {@code Status} value does not reflect the | 
|
     * state of a {@code SSLEngine} handshake currently | 
|
     * in progress.  The {@code SSLEngineResult's HandshakeStatus} | 
|
     * should be consulted for that information. | 
|
     * | 
|
     * @author Brad R. Wetmore | 
|
     * @since 1.5 | 
|
*/  | 
|
    public static enum Status { | 
|
        /** | 
|
         * The {@code SSLEngine} was not able to unwrap the | 
|
         * incoming data because there were not enough source bytes | 
|
         * available to make a complete packet. | 
|
         * | 
|
         * <P> | 
|
         * Repeat the call once more bytes are available. | 
|
*/  | 
|
BUFFER_UNDERFLOW,  | 
|
        /** | 
|
         * The {@code SSLEngine} was not able to process the | 
|
         * operation because there are not enough bytes available in the | 
|
         * destination buffer to hold the result. | 
|
         * <P> | 
|
         * Repeat the call once more bytes are available. | 
|
         * | 
|
         * @see SSLSession#getPacketBufferSize() | 
|
         * @see SSLSession#getApplicationBufferSize() | 
|
*/  | 
|
BUFFER_OVERFLOW,  | 
|
        /** | 
|
         * The {@code SSLEngine} completed the operation, and | 
|
         * is available to process similar calls. | 
|
*/  | 
|
OK,  | 
|
        /** | 
|
         * The operation just closed this side of the | 
|
         * {@code SSLEngine}, or the operation | 
|
         * could not be completed because it was already closed. | 
|
*/  | 
|
CLOSED;  | 
|
}  | 
|
    /** | 
|
     * An {@code SSLEngineResult} enum describing the current | 
|
     * handshaking state of this {@code SSLEngine}. | 
|
     * | 
|
     * @author Brad R. Wetmore | 
|
     * @since 1.5 | 
|
*/  | 
|
    public static enum HandshakeStatus { | 
|
        /** | 
|
         * The {@code SSLEngine} is not currently handshaking. | 
|
*/  | 
|
NOT_HANDSHAKING,  | 
|
        /** | 
|
         * The {@code SSLEngine} has just finished handshaking. | 
|
         * <P> | 
|
         * This value is only generated by a call to | 
|
         * {@code SSLEngine.wrap()/unwrap()} when that call | 
|
         * finishes a handshake.  It is never generated by | 
|
         * {@code SSLEngine.getHandshakeStatus()}. | 
|
         * | 
|
         * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) | 
|
         * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer) | 
|
         * @see SSLEngine#getHandshakeStatus() | 
|
*/  | 
|
FINISHED,  | 
|
        /** | 
|
         * The {@code SSLEngine} needs the results of one (or more) | 
|
         * delegated tasks before handshaking can continue. | 
|
         * | 
|
         * @see SSLEngine#getDelegatedTask() | 
|
*/  | 
|
NEED_TASK,  | 
|
        /** | 
|
         * The {@code SSLEngine} must send data to the remote side | 
|
         * before handshaking can continue, so {@code SSLEngine.wrap()} | 
|
         * should be called. | 
|
         * | 
|
         * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) | 
|
*/  | 
|
NEED_WRAP,  | 
|
        /** | 
|
         * The {@code SSLEngine} needs to receive data from the | 
|
         * remote side before handshaking can continue. | 
|
*/  | 
|
NEED_UNWRAP,  | 
|
        /** | 
|
         * The {@code SSLEngine} needs to unwrap before handshaking can | 
|
         * continue. | 
|
         * <P> | 
|
         * This value is used to indicate that not-yet-interpreted data | 
|
         * has been previously received from the remote side, and does | 
|
         * not need to be received again. | 
|
         * <P> | 
|
         * This handshake status only applies to DTLS. | 
|
         * | 
|
         * @since   9 | 
|
*/  | 
|
NEED_UNWRAP_AGAIN;  | 
|
}  | 
|
private final Status status;  | 
|
private final HandshakeStatus handshakeStatus;  | 
|
private final int bytesConsumed;  | 
|
private final int bytesProduced;  | 
|
private final long sequenceNumber;  | 
|
    /** | 
|
     * Initializes a new instance of this class. | 
|
     * | 
|
     * @param   status | 
|
     *          the return value of the operation. | 
|
     * | 
|
     * @param   handshakeStatus | 
|
     *          the current handshaking status. | 
|
     * | 
|
     * @param   bytesConsumed | 
|
     *          the number of bytes consumed from the source ByteBuffer | 
|
     * | 
|
     * @param   bytesProduced | 
|
     *          the number of bytes placed into the destination ByteBuffer | 
|
     * | 
|
     * @throws  IllegalArgumentException | 
|
     *          if the {@code status} or {@code handshakeStatus} | 
|
     *          arguments are null, or if {@code bytesConsumed} or | 
|
     *          {@code bytesProduced} is negative. | 
|
*/  | 
|
public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,  | 
|
            int bytesConsumed, int bytesProduced) { | 
|
this(status, handshakeStatus, bytesConsumed, bytesProduced, -1);  | 
|
}  | 
|
    /** | 
|
     * Initializes a new instance of this class. | 
|
     * | 
|
     * @param   status | 
|
     *          the return value of the operation. | 
|
     * | 
|
     * @param   handshakeStatus | 
|
     *          the current handshaking status. | 
|
     * | 
|
     * @param   bytesConsumed | 
|
     *          the number of bytes consumed from the source ByteBuffer | 
|
     * | 
|
     * @param   bytesProduced | 
|
     *          the number of bytes placed into the destination ByteBuffer | 
|
     * | 
|
     * @param   sequenceNumber | 
|
     *          the sequence number (unsigned long) of the produced or | 
|
     *          consumed SSL/TLS/DTLS record, or {@code -1L} if no record | 
|
     *          produced or consumed | 
|
     * | 
|
     * @throws  IllegalArgumentException | 
|
     *          if the {@code status} or {@code handshakeStatus} | 
|
     *          arguments are null, or if {@code bytesConsumed} or | 
|
     *          {@code bytesProduced} is negative | 
|
     * | 
|
     * @since   9 | 
|
*/  | 
|
public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,  | 
|
            int bytesConsumed, int bytesProduced, long sequenceNumber) { | 
|
if ((status == null) || (handshakeStatus == null) ||  | 
|
(bytesConsumed < 0) || (bytesProduced < 0)) {  | 
|
throw new IllegalArgumentException("Invalid Parameter(s)");  | 
|
}  | 
|
this.status = status;  | 
|
this.handshakeStatus = handshakeStatus;  | 
|
this.bytesConsumed = bytesConsumed;  | 
|
this.bytesProduced = bytesProduced;  | 
|
this.sequenceNumber = sequenceNumber;  | 
|
}  | 
|
    /** | 
|
     * Gets the return value of this {@code SSLEngine} operation. | 
|
     * | 
|
     * @return  the return value | 
|
*/  | 
|
    public final Status getStatus() { | 
|
return status;  | 
|
}  | 
|
    /** | 
|
     * Gets the handshake status of this {@code SSLEngine} | 
|
     * operation. | 
|
     * | 
|
     * @return  the handshake status | 
|
*/  | 
|
    public final HandshakeStatus getHandshakeStatus() { | 
|
return handshakeStatus;  | 
|
}  | 
|
    /** | 
|
     * Returns the number of bytes consumed from the input buffer. | 
|
     * | 
|
     * @return  the number of bytes consumed. | 
|
*/  | 
|
    public final int bytesConsumed() { | 
|
return bytesConsumed;  | 
|
}  | 
|
    /** | 
|
     * Returns the number of bytes written to the output buffer. | 
|
     * | 
|
     * @return  the number of bytes produced | 
|
*/  | 
|
    public final int bytesProduced() { | 
|
return bytesProduced;  | 
|
}  | 
|
    /** | 
|
     * Returns the sequence number of the produced or consumed SSL/TLS/DTLS | 
|
     * record (optional operation). | 
|
     * | 
|
     * @apiNote  Note that sequence number is an unsigned long and cannot | 
|
     *           exceed {@code -1L}.  It is desired to use the unsigned | 
|
     *           long comparing mode for comparison of unsigned long values | 
|
     *           (see also {@link java.lang.Long#compareUnsigned(long, long) | 
|
     *           Long.compareUnsigned()}). | 
|
     *           <P> | 
|
     *           For DTLS protocols, the first 16 bits of the sequence | 
|
     *           number is a counter value (epoch) that is incremented on | 
|
     *           every cipher state change.  The remaining 48 bits on the | 
|
     *           right side of the sequence number represents the sequence | 
|
     *           of the record, which is maintained separately for each epoch. | 
|
     * | 
|
     * @implNote It is recommended that providers should never allow the | 
|
     *           sequence number incremented to {@code -1L}.  If the sequence | 
|
     *           number is close to wrapping, renegotiate should be requested, | 
|
     *           otherwise the connection should be closed immediately. | 
|
     *           This should be carried on automatically by the underlying | 
|
     *           implementation. | 
|
     * | 
|
     * @return  the sequence number of the produced or consumed SSL/TLS/DTLS | 
|
     *          record; or {@code -1L} if no record is produced or consumed, | 
|
     *          or this operation is not supported by the underlying provider | 
|
     * | 
|
     * @see     java.lang.Long#compareUnsigned(long, long) | 
|
     * | 
|
     * @since   9 | 
|
*/  | 
|
    public final long sequenceNumber() { | 
|
return sequenceNumber;  | 
|
}  | 
|
    /** | 
|
     * Returns a String representation of this object. | 
|
*/  | 
|
@Override  | 
|
public String toString() {  | 
|
return ("Status = " + status +  | 
|
" HandshakeStatus = " + handshakeStatus +  | 
|
"\nbytesConsumed = " + bytesConsumed +  | 
|
" bytesProduced = " + bytesProduced +  | 
|
(sequenceNumber == -1 ? "" :  | 
|
" sequenceNumber = " + Long.toUnsignedString(sequenceNumber)));  | 
|
}  | 
|
}  |