History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/EngineWriter.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/EngineWriter.java+243−0
@@ -0,0 +1,243 @@
1+/*
2+ * Copyright (c) 2003, 2007, 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+
26+package sun.security.ssl;
27+
28+import javax.net.ssl.*;
29+import java.io.IOException;
30+import java.nio.ByteBuffer;
31+import java.util.LinkedList;
32+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
33+import sun.misc.HexDumpEncoder;
34+
35+/**
36+ * A class to help abstract away SSLEngine writing synchronization.
37+ */
38+final class EngineWriter {
39+
40+ /*
41+ * Outgoing handshake Data waiting for a ride is stored here.
42+ * Normal application data is written directly into the outbound
43+ * buffer, but handshake data can be written out at any time,
44+ * so we have buffer it somewhere.
45+ *
46+ * When wrap is called, we first check to see if there is
47+ * any data waiting, then if we're in a data transfer state,
48+ * we try to write app data.
49+ *
50+ * This will contain either ByteBuffers, or the marker
51+ * HandshakeStatus.FINISHED to signify that a handshake just completed.
52+ */
53+ private LinkedList<Object> outboundList;
54+
55+ private boolean outboundClosed = false;
56+
57+ /* Class and subclass dynamic debugging support */
58+ private static final Debug debug = Debug.getInstance("ssl");
59+
60+ EngineWriter() {
61+ outboundList = new LinkedList<Object>();
62+ }
63+
64+ /*
65+ * Upper levels assured us we had room for at least one packet of data.
66+ * As per the SSLEngine spec, we only return one SSL packets worth of
67+ * data.
68+ */
69+ private HandshakeStatus getOutboundData(ByteBuffer dstBB) {
70+
71+ Object msg = outboundList.removeFirst();
72+ assert(msg instanceof ByteBuffer);
73+
74+ ByteBuffer bbIn = (ByteBuffer) msg;
75+ assert(dstBB.remaining() >= bbIn.remaining());
76+
77+ dstBB.put(bbIn);
78+
79+ /*
80+ * If we have more data in the queue, it's either
81+ * a finished message, or an indication that we need
82+ * to call wrap again.
83+ */
84+ if (hasOutboundDataInternal()) {
85+ msg = outboundList.getFirst();
86+ if (msg == HandshakeStatus.FINISHED) {
87+ outboundList.removeFirst(); // consume the message
88+ return HandshakeStatus.FINISHED;
89+ } else {
90+ return HandshakeStatus.NEED_WRAP;
91+ }
92+ } else {
93+ return null;
94+ }
95+ }
96+
97+ /*
98+ * Properly orders the output of the data written to the wrap call.
99+ * This is only handshake data, application data goes through the
100+ * other writeRecord.
101+ */
102+ synchronized void writeRecord(EngineOutputRecord outputRecord,
103+ MAC writeMAC, CipherBox writeCipher) throws IOException {
104+
105+ /*
106+ * Only output if we're still open.
107+ */
108+ if (outboundClosed) {
109+ throw new IOException("writer side was already closed.");
110+ }
111+
112+ outputRecord.write(writeMAC, writeCipher);
113+
114+ /*
115+ * Did our handshakers notify that we just sent the
116+ * Finished message?
117+ *
118+ * Add an "I'm finished" message to the queue.
119+ */
120+ if (outputRecord.isFinishedMsg()) {
121+ outboundList.addLast(HandshakeStatus.FINISHED);
122+ }
123+ }
124+
125+ /*
126+ * Output the packet info.
127+ */
128+ private void dumpPacket(EngineArgs ea, boolean hsData) {
129+ try {
130+ HexDumpEncoder hd = new HexDumpEncoder();
131+
132+ ByteBuffer bb = ea.netData.duplicate();
133+
134+ int pos = bb.position();
135+ bb.position(pos - ea.deltaNet());
136+ bb.limit(pos);
137+
138+ System.out.println("[Raw write" +
139+ (hsData ? "" : " (bb)") + "]: length = " +
140+ bb.remaining());
141+ hd.encodeBuffer(bb, System.out);
142+ } catch (IOException e) { }
143+ }
144+
145+ /*
146+ * Properly orders the output of the data written to the wrap call.
147+ * Only app data goes through here, handshake data goes through
148+ * the other writeRecord.
149+ *
150+ * Shouldn't expect to have an IOException here.
151+ *
152+ * Return any determined status.
153+ */
154+ synchronized HandshakeStatus writeRecord(
155+ EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC,
156+ CipherBox writeCipher) throws IOException {
157+
158+ /*
159+ * If we have data ready to go, output this first before
160+ * trying to consume app data.
161+ */
162+ if (hasOutboundDataInternal()) {
163+ HandshakeStatus hss = getOutboundData(ea.netData);
164+
165+ if (debug != null && Debug.isOn("packet")) {
166+ /*
167+ * We could have put the dump in
168+ * OutputRecord.write(OutputStream), but let's actually
169+ * output when it's actually output by the SSLEngine.
170+ */
171+ dumpPacket(ea, true);
172+ }
173+
174+ return hss;
175+ }
176+
177+ /*
178+ * If we are closed, no more app data can be output.
179+ * Only existing handshake data (above) can be obtained.
180+ */
181+ if (outboundClosed) {
182+ throw new IOException("The write side was already closed");
183+ }
184+
185+ outputRecord.write(ea, writeMAC, writeCipher);
186+
187+ if (debug != null && Debug.isOn("packet")) {
188+ dumpPacket(ea, false);
189+ }
190+
191+ /*
192+ * No way new outbound handshake data got here if we're
193+ * locked properly.
194+ *
195+ * We don't have any status we can return.
196+ */
197+ return null;
198+ }
199+
200+ /*
201+ * We already hold "this" lock, this is the callback from the
202+ * outputRecord.write() above. We already know this
203+ * writer can accept more data (outboundClosed == false),
204+ * and the closure is sync'd.
205+ */
206+ void putOutboundData(ByteBuffer bytes) {
207+ outboundList.addLast(bytes);
208+ }
209+
210+ /*
211+ * This is for the really rare case that someone is writing from
212+ * the *InputRecord* before we know what to do with it.
213+ */
214+ synchronized void putOutboundDataSync(ByteBuffer bytes)
215+ throws IOException {
216+
217+ if (outboundClosed) {
218+ throw new IOException("Write side already closed");
219+ }
220+
221+ outboundList.addLast(bytes);
222+ }
223+
224+ /*
225+ * Non-synch'd version of this method, called by internals
226+ */
227+ private boolean hasOutboundDataInternal() {
228+ return (outboundList.size() != 0);
229+ }
230+
231+ synchronized boolean hasOutboundData() {
232+ return hasOutboundDataInternal();
233+ }
234+
235+ synchronized boolean isOutboundDone() {
236+ return outboundClosed && !hasOutboundDataInternal();
237+ }
238+
239+ synchronized void closeOutbound() {
240+ outboundClosed = true;
241+ }
242+
243+}