--- old/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java Fri May 29 00:47:53 2015 +++ new/src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java Fri May 29 00:47:53 2015 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015, 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 @@ -23,11 +23,11 @@ * questions. */ - package sun.security.ssl; -import java.io.InputStream; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.nio.ByteBuffer; import javax.net.ssl.SSLException; @@ -38,154 +38,104 @@ * Once a new handshake record arrives, it is buffered in this class until * processed by the Handshaker. The buffer may also contain incomplete * handshake messages in case the message is split across multiple records. - * Handshaker.process_record deals with all that. It may also contain + * Handshaker.processRecord deals with all that. It may also contain * handshake messages larger than the default buffer size (e.g. large - * certificate messages). The buffer is grown dynamically to handle that - * (see InputRecord.queueHandshake()). + * certificate messages). The buffer is grown dynamically to handle that. * - * Note that the InputRecord used as a buffer here is separate from the - * AppInStream.r, which is where data from the socket is initially read - * into. This is because once the initial handshake has been completed, - * handshake and application data messages may be interleaved arbitrarily - * and must be processed independently. + * Note that this class only handles Handshake messages in TLS format. + * DTLS Handshake messages should be converted into TLS format before + * calling into this method. * * @author David Brownell */ -public class HandshakeInStream extends InputStream { - InputRecord r; +// This class is used to handle plain text handshake messages. +// +public final class HandshakeInStream extends ByteArrayInputStream { /* * Construct the stream; we'll be accumulating hashes of the * input records using two sets of digests. */ - HandshakeInStream(HandshakeHash handshakeHash) { - r = new InputRecord(); - r.setHandshakeHash(handshakeHash); + HandshakeInStream() { + super(new byte[0]); // lazy to alloacte the internal buffer } + // + // overridden ByteArrayInputStream methods + // - // overridden InputStream methods - - /* - * Return the number of bytes available for read(). - * - * Note that this returns the bytes remaining in the buffer, not - * the bytes remaining in the current handshake message. - */ @Override - public int available() { - return r.available(); - } - - /* - * Get a byte of handshake data. - */ - @Override - public int read() throws IOException { - int n = r.read(); - if (n == -1) { + public int read(byte[] b) throws IOException { + if (super.read(b) != b.length) { throw new SSLException("Unexpected end of handshake data"); } - return n; - } - /* - * Get a bunch of bytes of handshake data. - */ - @Override - public int read(byte b [], int off, int len) throws IOException { - // we read from a ByteArrayInputStream, it always returns the - // data in a single read if enough is available - int n = r.read(b, off, len); - if (n != len) { - throw new SSLException("Unexpected end of handshake data"); - } - return n; + return b.length; } - /* - * Skip some handshake data. - */ - @Override - public long skip(long n) throws IOException { - return r.skip(n); - } + // + // handshake input stream management functions + // /* - * Mark/ reset code, implemented using InputRecord mark/ reset. - * - * Note that it currently provides only a limited mark functionality - * and should be used with care (once a new handshake record has been - * read, data that has already been consumed is lost even if marked). - */ - - @Override - public void mark(int readlimit) { - r.mark(readlimit); - } - - @Override - public void reset() throws IOException { - r.reset(); - } - - @Override - public boolean markSupported() { - return true; - } - - - // handshake management functions - - /* * Here's an incoming record with handshake data. Queue the contents; * it might be one or more entire messages, complete a message that's * partly queued, or both. */ - void incomingRecord(InputRecord in) throws IOException { - r.queueHandshake(in); - } + void incomingRecord(ByteBuffer in) throws IOException { + int len; - /* - * Hash any data we've consumed but not yet hashed. Useful mostly - * for processing client certificate messages (so we can check the - * immediately following cert verify message) and finished messages - * (so we can compute our own finished message). - */ - void digestNow() { - r.doHashes(); - } + // Move any unread data to the front of the buffer. + if (pos != 0) { + len = count - pos; + if (len != 0) { + System.arraycopy(buf, pos, buf, 0, len); + } + pos = 0; + count = len; + } - /* - * Do more than skip that handshake data ... totally ignore it. - * The difference is that the data does not get hashed. - */ - void ignore(int n) { - r.ignore(n); + // Grow buffer if needed. + len = in.remaining() + count; + if (buf.length < len) { + byte[] newbuf = new byte[len]; + if (count != 0) { + System.arraycopy(buf, 0, newbuf, 0, count); + } + buf = newbuf; + } + + // Append the incoming record to the buffer + in.get(buf, count, in.remaining()); + count = len; } - + // // Message parsing methods + // /* * Read 8, 16, 24, and 32 bit SSL integer data types, encoded * in standard big-endian form. */ - int getInt8() throws IOException { + verifyLength(1); return read(); } int getInt16() throws IOException { + verifyLength(2); return (getInt8() << 8) | getInt8(); } int getInt24() throws IOException { + verifyLength(3); return (getInt8() << 16) | (getInt8() << 8) | getInt8(); } int getInt32() throws IOException { + verifyLength(4); return (getInt8() << 24) | (getInt8() << 16) | (getInt8() << 8) | getInt8(); } @@ -193,13 +143,12 @@ /* * Read byte vectors with 8, 16, and 24 bit length encodings. */ - byte[] getBytes8() throws IOException { int len = getInt8(); verifyLength(len); byte b[] = new byte[len]; - read(b, 0, len); + read(b); return b; } @@ -208,7 +157,7 @@ verifyLength(len); byte b[] = new byte[len]; - read(b, 0, len); + read(b); return b; } @@ -217,7 +166,7 @@ verifyLength(len); byte b[] = new byte[len]; - read(b, 0, len); + read(b); return b; } @@ -224,9 +173,7 @@ // Is a length greater than available bytes in the record? private void verifyLength(int len) throws SSLException { if (len > available()) { - throw new SSLException( - "Not enough data to fill declared vector size"); + throw new SSLException("Unexpected end of handshake data"); } } - }