--- old/src/java.base/share/classes/sun/security/ssl/EngineWriter.java Fri May 29 00:49:04 2015 +++ /dev/null Fri May 29 00:49:05 2015 @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2003, 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.IOException; -import java.nio.ByteBuffer; -import java.util.LinkedList; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import sun.misc.HexDumpEncoder; - -/** - * A class to help abstract away SSLEngine writing synchronization. - */ -final class EngineWriter { - - /* - * Outgoing handshake Data waiting for a ride is stored here. - * Normal application data is written directly into the outbound - * buffer, but handshake data can be written out at any time, - * so we have buffer it somewhere. - * - * When wrap is called, we first check to see if there is - * any data waiting, then if we're in a data transfer state, - * we try to write app data. - * - * This will contain either ByteBuffers, or the marker - * HandshakeStatus.FINISHED to signify that a handshake just completed. - */ - private LinkedList outboundList; - - private boolean outboundClosed = false; - - /* Class and subclass dynamic debugging support */ - private static final Debug debug = Debug.getInstance("ssl"); - - EngineWriter() { - outboundList = new LinkedList(); - } - - /* - * Upper levels assured us we had room for at least one packet of data. - * As per the SSLEngine spec, we only return one SSL packets worth of - * data. - */ - private HandshakeStatus getOutboundData(ByteBuffer dstBB) { - - Object msg = outboundList.removeFirst(); - assert(msg instanceof ByteBuffer); - - ByteBuffer bbIn = (ByteBuffer) msg; - assert(dstBB.remaining() >= bbIn.remaining()); - - dstBB.put(bbIn); - - /* - * If we have more data in the queue, it's either - * a finished message, or an indication that we need - * to call wrap again. - */ - if (hasOutboundDataInternal()) { - msg = outboundList.getFirst(); - if (msg == HandshakeStatus.FINISHED) { - outboundList.removeFirst(); // consume the message - return HandshakeStatus.FINISHED; - } else { - return HandshakeStatus.NEED_WRAP; - } - } else { - return null; - } - } - - /* - * Properly orders the output of the data written to the wrap call. - * This is only handshake data, application data goes through the - * other writeRecord. - */ - synchronized void writeRecord(EngineOutputRecord outputRecord, - Authenticator authenticator, - CipherBox writeCipher) throws IOException { - - /* - * Only output if we're still open. - */ - if (outboundClosed) { - throw new IOException("writer side was already closed."); - } - - outputRecord.write(authenticator, writeCipher); - - /* - * Did our handshakers notify that we just sent the - * Finished message? - * - * Add an "I'm finished" message to the queue. - */ - if (outputRecord.isFinishedMsg()) { - outboundList.addLast(HandshakeStatus.FINISHED); - } - } - - /* - * Output the packet info. - */ - private void dumpPacket(EngineArgs ea, boolean hsData) { - try { - HexDumpEncoder hd = new HexDumpEncoder(); - - ByteBuffer bb = ea.netData.duplicate(); - - int pos = bb.position(); - bb.position(pos - ea.deltaNet()); - bb.limit(pos); - - System.out.println("[Raw write" + - (hsData ? "" : " (bb)") + "]: length = " + - bb.remaining()); - hd.encodeBuffer(bb, System.out); - } catch (IOException e) { } - } - - /* - * Properly orders the output of the data written to the wrap call. - * Only app data goes through here, handshake data goes through - * the other writeRecord. - * - * Shouldn't expect to have an IOException here. - * - * Return any determined status. - */ - synchronized HandshakeStatus writeRecord( - EngineOutputRecord outputRecord, EngineArgs ea, - Authenticator authenticator, - CipherBox writeCipher) throws IOException { - - /* - * If we have data ready to go, output this first before - * trying to consume app data. - */ - if (hasOutboundDataInternal()) { - HandshakeStatus hss = getOutboundData(ea.netData); - - if (debug != null && Debug.isOn("packet")) { - /* - * We could have put the dump in - * OutputRecord.write(OutputStream), but let's actually - * output when it's actually output by the SSLEngine. - */ - dumpPacket(ea, true); - } - - return hss; - } - - /* - * If we are closed, no more app data can be output. - * Only existing handshake data (above) can be obtained. - */ - if (outboundClosed) { - throw new IOException("The write side was already closed"); - } - - outputRecord.write(ea, authenticator, writeCipher); - - if (debug != null && Debug.isOn("packet")) { - dumpPacket(ea, false); - } - - /* - * No way new outbound handshake data got here if we're - * locked properly. - * - * We don't have any status we can return. - */ - return null; - } - - /* - * We already hold "this" lock, this is the callback from the - * outputRecord.write() above. We already know this - * writer can accept more data (outboundClosed == false), - * and the closure is sync'd. - */ - void putOutboundData(ByteBuffer bytes) { - outboundList.addLast(bytes); - } - - /* - * This is for the really rare case that someone is writing from - * the *InputRecord* before we know what to do with it. - */ - synchronized void putOutboundDataSync(ByteBuffer bytes) - throws IOException { - - if (outboundClosed) { - throw new IOException("Write side already closed"); - } - - outboundList.addLast(bytes); - } - - /* - * Non-synch'd version of this method, called by internals - */ - private boolean hasOutboundDataInternal() { - return (outboundList.size() != 0); - } - - synchronized boolean hasOutboundData() { - return hasOutboundDataInternal(); - } - - synchronized boolean isOutboundDone() { - return outboundClosed && !hasOutboundDataInternal(); - } - - synchronized void closeOutbound() { - outboundClosed = true; - } - -}