/* * Copyright (c) 1996, 2013, 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.ByteArrayOutputStream; import java.io.IOException; /** * Output stream for handshake data. This is used only internally * to the SSL classes. * * MT note: one thread at a time is presumed be writing handshake * messages, but (after initial connection setup) it's possible to * have other threads reading/writing application data. It's the * SSLSocketImpl class that synchronizes record writes. * * @author David Brownell */ public class HandshakeOutStream extends ByteArrayOutputStream { OutputRecord outputRecord; // May be null if not actually used to // output handshake message records. HandshakeOutStream(OutputRecord outputRecord) { super(); this.outputRecord = outputRecord; } // Complete a handshakin message writing. Called by HandshakeMessage. void complete() throws IOException { if (size() < 4) { // 4: handshake message header size // internal_error alert will be triggered throw new RuntimeException("handshake message is not available"); } // outputRecord cannot be null outputRecord.encodeHandshake(buf, 0, count); // reset the byte array output stream reset(); } // // overridden ByteArrayOutputStream methods // @Override public void write(byte[] b, int off, int len) { // The maximum fragment size is 24 bytes. checkOverflow(len, Record.OVERFLOW_OF_INT24); super.write(b, off, len); } @Override public void flush() throws IOException { outputRecord.flush(); } // // handshake output stream management functions // /* * Put integers encoded in standard 8, 16, 24, and 32 bit * big endian formats. Note that OutputStream.write(int) only * writes the least significant 8 bits and ignores the rest. */ void putInt8(int i) throws IOException { checkOverflow(i, Record.OVERFLOW_OF_INT08); super.write(i); } void putInt16(int i) throws IOException { checkOverflow(i, Record.OVERFLOW_OF_INT16); super.write(i >> 8); super.write(i); } void putInt24(int i) throws IOException { checkOverflow(i, Record.OVERFLOW_OF_INT24); super.write(i >> 16); super.write(i >> 8); super.write(i); } /* * Put byte arrays with length encoded as 8, 16, 24 bit * integers in big-endian format. */ void putBytes8(byte[] b) throws IOException { if (b == null) { putInt8(0); } else { putInt8(b.length); super.write(b, 0, b.length); } } public void putBytes16(byte[] b) throws IOException { if (b == null) { putInt16(0); } else { putInt16(b.length); super.write(b, 0, b.length); } } void putBytes24(byte[] b) throws IOException { if (b == null) { putInt24(0); } else { putInt24(b.length); super.write(b, 0, b.length); } } /* * Does the specified length overflow the limitation? */ private static void checkOverflow(int length, int limit) { if (length >= limit) { // internal_error alert will be triggered throw new RuntimeException( "Field length overflow, the field length (" + length + ") should be less than " + limit); } } }