SSLEngineResult.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package javax.net.ssl; 27 28/** 29 * An encapsulation of the result state produced by 30 * {@code SSLEngine} I/O calls. 31 * 32 * <p> A {@code SSLEngine} provides a means for establishing 33 * secure communication sessions between two peers. {@code SSLEngine} 34 * operations typically consume bytes from an input buffer and produce 35 * bytes in an output buffer. This class provides operational result 36 * values describing the state of the {@code SSLEngine}, including 37 * indications of what operations are needed to finish an 38 * ongoing handshake. Lastly, it reports the number of bytes consumed 39 * and produced as a result of this operation. 40 * 41 * @see SSLEngine 42 * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) 43 * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer) 44 * 45 * @author Brad R. Wetmore 46 * @since 1.5 47 */ 48 49public class SSLEngineResult { 50 51 /** 52 * An {@code SSLEngineResult} enum describing the overall result 53 * of the {@code SSLEngine} operation. 54 * 55 * The {@code Status} value does not reflect the 56 * state of a {@code SSLEngine} handshake currently 57 * in progress. The {@code SSLEngineResult's HandshakeStatus} 58 * should be consulted for that information. 59 * 60 * @author Brad R. Wetmore 61 * @since 1.5 62 */ 63 public static enum Status { 64 65 /** 66 * The {@code SSLEngine} was not able to unwrap the 67 * incoming data because there were not enough source bytes 68 * available to make a complete packet. 69 * 70 * <P> 71 * Repeat the call once more bytes are available. 72 */ 73 BUFFER_UNDERFLOW, 74 75 /** 76 * The {@code SSLEngine} was not able to process the 77 * operation because there are not enough bytes available in the 78 * destination buffer to hold the result. 79 * <P> 80 * Repeat the call once more bytes are available. 81 * 82 * @see SSLSession#getPacketBufferSize() 83 * @see SSLSession#getApplicationBufferSize() 84 */ 85 BUFFER_OVERFLOW, 86 87 /** 88 * The {@code SSLEngine} completed the operation, and 89 * is available to process similar calls. 90 */ 91 OK, 92 93 /** 94 * The operation just closed this side of the 95 * {@code SSLEngine}, or the operation 96 * could not be completed because it was already closed. 97 */ 98 CLOSED; 99 } 100 101 /** 102 * An {@code SSLEngineResult} enum describing the current 103 * handshaking state of this {@code SSLEngine}. 104 * 105 * @author Brad R. Wetmore 106 * @since 1.5 107 */ 108 public static enum HandshakeStatus { 109 110 /** 111 * The {@code SSLEngine} is not currently handshaking. 112 */ 113 NOT_HANDSHAKING, 114 115 /** 116 * The {@code SSLEngine} has just finished handshaking. 117 * <P> 118 * This value is only generated by a call to 119 * {@code SSLEngine.wrap()/unwrap()} when that call 120 * finishes a handshake. It is never generated by 121 * {@code SSLEngine.getHandshakeStatus()}. 122 * 123 * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) 124 * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer) 125 * @see SSLEngine#getHandshakeStatus() 126 */ 127 FINISHED, 128 129 /** 130 * The {@code SSLEngine} needs the results of one (or more) 131 * delegated tasks before handshaking can continue. 132 * 133 * @see SSLEngine#getDelegatedTask() 134 */ 135 NEED_TASK, 136 137 /** 138 * The {@code SSLEngine} must send data to the remote side 139 * before handshaking can continue, so {@code SSLEngine.wrap()} 140 * should be called. 141 * 142 * @see SSLEngine#wrap(ByteBuffer, ByteBuffer) 143 */ 144 NEED_WRAP, 145 146 /** 147 * The {@code SSLEngine} needs to receive data from the 148 * remote side before handshaking can continue. 149 */ 150 NEED_UNWRAP, 151 152 /** 153 * The {@code SSLEngine} needs to unwrap before handshaking can 154 * can continue. 155 * <P> 156 * This value is used to indicate that not-yet-interpreted data 157 * has been previously received from the remote side, and does 158 * not need to be received again. 159 * <P> 160 * This handshake status only applies to DTLS. 161 * 162 * @since 9 163 */ 164 NEED_UNWRAP_AGAIN; 165 } 166 167 168 private final Status status; 169 private final HandshakeStatus handshakeStatus; 170 private final int bytesConsumed; 171 private final int bytesProduced; 172 private final long sequenceNumber; 173 174 /** 175 * Initializes a new instance of this class. 176 * 177 * @param status 178 * the return value of the operation. 179 * 180 * @param handshakeStatus 181 * the current handshaking status. 182 * 183 * @param bytesConsumed 184 * the number of bytes consumed from the source ByteBuffer 185 * 186 * @param bytesProduced 187 * the number of bytes placed into the destination ByteBuffer 188 * 189 * @throws IllegalArgumentException 190 * if the {@code status} or {@code handshakeStatus} 191 * arguments are null, or if {@code bytesConsumed} or 192 * {@code bytesProduced} is negative. 193 */ 194 public SSLEngineResult(Status status, HandshakeStatus handshakeStatus, 195 int bytesConsumed, int bytesProduced) { 196 this(status, handshakeStatus, bytesConsumed, bytesProduced, -1); 197 } 198 199 /** 200 * Initializes a new instance of this class. 201 * 202 * @param status 203 * the return value of the operation. 204 * 205 * @param handshakeStatus 206 * the current handshaking status. 207 * 208 * @param bytesConsumed 209 * the number of bytes consumed from the source ByteBuffer 210 * 211 * @param bytesProduced 212 * the number of bytes placed into the destination ByteBuffer 213 * 214 * @param sequenceNumber 215 * the sequence number (unsigned long) of the produced or 216 * consumed SSL/TLS/DTLS record, or ${@code -1L} if no record 217 * produced or consumed 218 * 219 * @throws IllegalArgumentException 220 * if the {@code status} or {@code handshakeStatus} 221 * arguments are null, or if {@code bytesConsumed} or 222 * {@code bytesProduced} is negative 223 * 224 * @since 9 225 */ 226 public SSLEngineResult(Status status, HandshakeStatus handshakeStatus, 227 int bytesConsumed, int bytesProduced, long sequenceNumber) { 228 229 if ((status == null) || (handshakeStatus == null) || 230 (bytesConsumed < 0) || (bytesProduced < 0)) { 231 throw new IllegalArgumentException("Invalid Parameter(s)"); 232 } 233 234 this.status = status; 235 this.handshakeStatus = handshakeStatus; 236 this.bytesConsumed = bytesConsumed; 237 this.bytesProduced = bytesProduced; 238 this.sequenceNumber = sequenceNumber; 239 } 240 241 /** 242 * Gets the return value of this {@code SSLEngine} operation. 243 * 244 * @return the return value 245 */ 246 public final Status getStatus() { 247 return status; 248 } 249 250 /** 251 * Gets the handshake status of this {@code SSLEngine} 252 * operation. 253 * 254 * @return the handshake status 255 */ 256 public final HandshakeStatus getHandshakeStatus() { 257 return handshakeStatus; 258 } 259 260 /** 261 * Returns the number of bytes consumed from the input buffer. 262 * 263 * @return the number of bytes consumed. 264 */ 265 public final int bytesConsumed() { 266 return bytesConsumed; 267 } 268 269 /** 270 * Returns the number of bytes written to the output buffer. 271 * 272 * @return the number of bytes produced 273 */ 274 public final int bytesProduced() { 275 return bytesProduced; 276 } 277 278 /** 279 * Returns the sequence number of the produced or consumed SSL/TLS/DTLS 280 * record (optional operation). 281 * 282 * @apiNote Note that sequence number is an unsigned long and cannot 283 * exceed {@code -1L}. It is desired to use the unsigned 284 * long comparing mode for comparison of unsigned long values 285 * (see also {@link java.lang.Long#compareUnsigned(long, long) 286 * Long.compareUnsigned()}). 287 * <P> 288 * For DTLS protocols, the first 16 bits of the sequence 289 * number is a counter value (epoch) that is incremented on 290 * every cipher state change. The remaining 48 bits on the 291 * right side of the sequence number represents the sequence 292 * of the record, which is maintained separately for each epoch. 293 * 294 * @implNote It is recommended that providers should never allow the 295 * sequence number incremented to {@code -1L}. If the sequence 296 * number is close to wrapping, renegotiate should be requested, 297 * otherwise the connection should be closed immediately. 298 * This should be carried on automatically by the underlying 299 * implementation. 300 * 301 * @return the sequence number of the produced or consumed SSL/TLS/DTLS 302 * record; or ${@code -1L} if no record is produced or consumed, 303 * or this operation is not supported by the underlying provider 304 * 305 * @see java.lang.Long#compareUnsigned(long, long) 306 * 307 * @since 9 308 */ 309 public final long sequenceNumber() { 310 return sequenceNumber; 311 } 312 313 /** 314 * Returns a String representation of this object. 315 */ 316 @Override 317 public String toString() { 318 return ("Status = " + status + 319 " HandshakeStatus = " + handshakeStatus + 320 "\nbytesConsumed = " + bytesConsumed + 321 " bytesProduced = " + bytesProduced + 322 (sequenceNumber == -1 ? "" : 323 " sequenceNumber = " + Long.toUnsignedString(sequenceNumber))); 324 } 325} 326