< prev index next >

src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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

@@ -49,210 +49,127 @@
         this.packetSize = SSLRecord.maxRecordSize;
         this.protocolVersion = ProtocolVersion.NONE;
     }
 
     @Override
-    void encodeAlert(byte level, byte description) throws IOException {
-        recordLock.lock();
-        try {
-            if (isClosed()) {
-                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
-                    SSLLogger.warning("outbound has closed, ignore outbound " +
-                        "alert message: " + Alert.nameOf(description));
-                }
-                return;
-            }
-
-            // use the buf of ByteArrayOutputStream
-            int position = headerSize + writeCipher.getExplicitNonceSize();
-            count = position;
-
-            write(level);
-            write(description);
-            if (SSLLogger.isOn && SSLLogger.isOn("record")) {
-                SSLLogger.fine("WRITE: " + protocolVersion +
-                        " " + ContentType.ALERT.name +
-                        "(" + Alert.nameOf(description) + ")" +
-                        ", length = " + (count - headerSize));
+    synchronized void encodeAlert(
+            byte level, byte description) throws IOException {
+        if (isClosed()) {
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                SSLLogger.warning("outbound has closed, ignore outbound " +
+                    "alert message: " + Alert.nameOf(description));
             }
+            return;
+        }
 
-            // Encrypt the fragment and wrap up a record.
-            encrypt(writeCipher, ContentType.ALERT.id, headerSize);
-
-            // deliver this message
-            deliverStream.write(buf, 0, count);    // may throw IOException
-            deliverStream.flush();                 // may throw IOException
+        // use the buf of ByteArrayOutputStream
+        int position = headerSize + writeCipher.getExplicitNonceSize();
+        count = position;
+
+        write(level);
+        write(description);
+        if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+            SSLLogger.fine("WRITE: " + protocolVersion +
+                    " " + ContentType.ALERT.name +
+                    "(" + Alert.nameOf(description) + ")" +
+                    ", length = " + (count - headerSize));
+        }
 
-            if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
-                SSLLogger.fine("Raw write",
-                        (new ByteArrayInputStream(buf, 0, count)));
-            }
+        // Encrypt the fragment and wrap up a record.
+        encrypt(writeCipher, ContentType.ALERT.id, headerSize);
 
-            // reset the internal buffer
-            count = 0;
-        } finally {
-            recordLock.unlock();
+        // deliver this message
+        deliverStream.write(buf, 0, count);    // may throw IOException
+        deliverStream.flush();                 // may throw IOException
+
+        if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+            SSLLogger.fine("Raw write",
+                    (new ByteArrayInputStream(buf, 0, count)));
         }
+
+        // reset the internal buffer
+        count = 0;
     }
 
     @Override
-    void encodeHandshake(byte[] source,
+    synchronized void encodeHandshake(byte[] source,
             int offset, int length) throws IOException {
-        recordLock.lock();
-        try {
-            if (isClosed()) {
-                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
-                    SSLLogger.warning("outbound has closed, ignore outbound " +
-                            "handshake message",
-                            ByteBuffer.wrap(source, offset, length));
-                }
-                return;
+        if (isClosed()) {
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                SSLLogger.warning("outbound has closed, ignore outbound " +
+                        "handshake message",
+                        ByteBuffer.wrap(source, offset, length));
             }
+            return;
+        }
 
-            if (firstMessage) {
-                firstMessage = false;
+        if (firstMessage) {
+            firstMessage = false;
 
-                if ((helloVersion == ProtocolVersion.SSL20Hello) &&
-                    (source[offset] == SSLHandshake.CLIENT_HELLO.id) &&
+            if ((helloVersion == ProtocolVersion.SSL20Hello) &&
+                (source[offset] == SSLHandshake.CLIENT_HELLO.id) &&
                                             //  5: recode header size
-                    (source[offset + 4 + 2 + 32] == 0)) {
+                (source[offset + 4 + 2 + 32] == 0)) {
                                             // V3 session ID is empty
                                             //  4: handshake header size
                                             //  2: client_version in ClientHello
                                             // 32: random in ClientHello
 
-                    ByteBuffer v2ClientHello = encodeV2ClientHello(
-                            source, (offset + 4), (length - 4));
-
-                    // array offset is zero
-                    byte[] record = v2ClientHello.array();
-                    int limit = v2ClientHello.limit();
-                    handshakeHash.deliver(record, 2, (limit - 2));
-
-                    if (SSLLogger.isOn && SSLLogger.isOn("record")) {
-                        SSLLogger.fine(
-                                "WRITE: SSLv2 ClientHello message" +
-                                ", length = " + limit);
-                    }
-
-                    // deliver this message
-                    //
-                    // Version 2 ClientHello message should be plaintext.
-                    //
-                    // No max fragment length negotiation.
-                    deliverStream.write(record, 0, limit);
-                    deliverStream.flush();
-
-                    if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
-                        SSLLogger.fine("Raw write",
-                                (new ByteArrayInputStream(record, 0, limit)));
-                    }
-
-                    return;
-                }
-            }
-
-            byte handshakeType = source[0];
-            if (handshakeHash.isHashable(handshakeType)) {
-                handshakeHash.deliver(source, offset, length);
-            }
-
-            int fragLimit = getFragLimit();
-            int position = headerSize + writeCipher.getExplicitNonceSize();
-            if (count == 0) {
-                count = position;
-            }
-
-            if ((count - position) < (fragLimit - length)) {
-                write(source, offset, length);
-                return;
-            }
-
-            for (int limit = (offset + length); offset < limit;) {
-
-                int remains = (limit - offset) + (count - position);
-                int fragLen = Math.min(fragLimit, remains);
+                ByteBuffer v2ClientHello = encodeV2ClientHello(
+                        source, (offset + 4), (length - 4));
 
-                // use the buf of ByteArrayOutputStream
-                write(source, offset, fragLen);
-                if (remains < fragLimit) {
-                    return;
-                }
+                byte[] record = v2ClientHello.array();  // array offset is zero
+                int limit = v2ClientHello.limit();
+                handshakeHash.deliver(record, 2, (limit - 2));
 
                 if (SSLLogger.isOn && SSLLogger.isOn("record")) {
                     SSLLogger.fine(
-                            "WRITE: " + protocolVersion +
-                            " " + ContentType.HANDSHAKE.name +
-                            ", length = " + (count - headerSize));
+                            "WRITE: SSLv2 ClientHello message" +
+                            ", length = " + limit);
                 }
 
-                // Encrypt the fragment and wrap up a record.
-                encrypt(writeCipher, ContentType.HANDSHAKE.id, headerSize);
-
                 // deliver this message
-                deliverStream.write(buf, 0, count);    // may throw IOException
-                deliverStream.flush();                 // may throw IOException
+                //
+                // Version 2 ClientHello message should be plaintext.
+                //
+                // No max fragment length negotiation.
+                deliverStream.write(record, 0, limit);
+                deliverStream.flush();
 
                 if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
                     SSLLogger.fine("Raw write",
-                            (new ByteArrayInputStream(buf, 0, count)));
+                            (new ByteArrayInputStream(record, 0, limit)));
                 }
 
-                // reset the offset
-                offset += fragLen;
-
-                // reset the internal buffer
-                count = position;
+                return;
             }
-        } finally {
-            recordLock.unlock();
         }
-    }
 
-    @Override
-    void encodeChangeCipherSpec() throws IOException {
-        recordLock.lock();
-        try {
-            if (isClosed()) {
-                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
-                    SSLLogger.warning("outbound has closed, ignore outbound " +
-                        "change_cipher_spec message");
-                }
-                return;
-            }
+        byte handshakeType = source[0];
+        if (handshakeHash.isHashable(handshakeType)) {
+            handshakeHash.deliver(source, offset, length);
+        }
 
-            // use the buf of ByteArrayOutputStream
-            int position = headerSize + writeCipher.getExplicitNonceSize();
+        int fragLimit = getFragLimit();
+        int position = headerSize + writeCipher.getExplicitNonceSize();
+        if (count == 0) {
             count = position;
+        }
 
-            write((byte)1);         // byte 1: change_cipher_spec(
-
-            // Encrypt the fragment and wrap up a record.
-            encrypt(writeCipher, ContentType.CHANGE_CIPHER_SPEC.id, headerSize);
-
-            // deliver this message
-            deliverStream.write(buf, 0, count);        // may throw IOException
-            // deliverStream.flush();                  // flush in Finished
+        if ((count - position) < (fragLimit - length)) {
+            write(source, offset, length);
+            return;
+        }
 
-            if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
-                SSLLogger.fine("Raw write",
-                        (new ByteArrayInputStream(buf, 0, count)));
-            }
+        for (int limit = (offset + length); offset < limit;) {
 
-            // reset the internal buffer
-            count = 0;
-        } finally {
-            recordLock.unlock();
-        }
-    }
+            int remains = (limit - offset) + (count - position);
+            int fragLen = Math.min(fragLimit, remains);
 
-    @Override
-    public void flush() throws IOException {
-        recordLock.lock();
-        try {
-            int position = headerSize + writeCipher.getExplicitNonceSize();
-            if (count <= position) {
+            // use the buf of ByteArrayOutputStream
+            write(source, offset, fragLen);
+            if (remains < fragLimit) {
                 return;
             }
 
             if (SSLLogger.isOn && SSLLogger.isOn("record")) {
                 SSLLogger.fine(

@@ -271,107 +188,159 @@
             if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
                 SSLLogger.fine("Raw write",
                         (new ByteArrayInputStream(buf, 0, count)));
             }
 
+            // reset the offset
+            offset += fragLen;
+
             // reset the internal buffer
-            count = 0;      // DON'T use position
-        } finally {
-            recordLock.unlock();
+            count = position;
         }
     }
 
     @Override
-    void deliver(byte[] source, int offset, int length) throws IOException {
-        recordLock.lock();
-        try {
-            if (isClosed()) {
-                throw new SocketException(
-                        "Connection or outbound has been closed");
+    synchronized void encodeChangeCipherSpec() throws IOException {
+        if (isClosed()) {
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                SSLLogger.warning("outbound has closed, ignore outbound " +
+                    "change_cipher_spec message");
             }
+            return;
+        }
 
-            if (writeCipher.authenticator.seqNumOverflow()) {
-                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
-                    SSLLogger.fine(
-                        "sequence number extremely close to overflow " +
-                        "(2^64-1 packets). Closing connection.");
-                }
+        // use the buf of ByteArrayOutputStream
+        int position = headerSize + writeCipher.getExplicitNonceSize();
+        count = position;
+
+        write((byte)1);         // byte 1: change_cipher_spec(
+
+        // Encrypt the fragment and wrap up a record.
+        encrypt(writeCipher, ContentType.CHANGE_CIPHER_SPEC.id, headerSize);
+
+        // deliver this message
+        deliverStream.write(buf, 0, count);        // may throw IOException
+        // deliverStream.flush();                  // flush in Finished
+
+        if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+            SSLLogger.fine("Raw write",
+                    (new ByteArrayInputStream(buf, 0, count)));
+        }
 
-                throw new SSLHandshakeException("sequence number overflow");
-            }
+        // reset the internal buffer
+        count = 0;
+    }
 
-            boolean isFirstRecordOfThePayload = true;
-            for (int limit = (offset + length); offset < limit;) {
-                int fragLen;
-                if (packetSize > 0) {
-                    fragLen = Math.min(maxRecordSize, packetSize);
-                    fragLen = writeCipher.calculateFragmentSize(
-                            fragLen, headerSize);
-
-                    fragLen = Math.min(fragLen, Record.maxDataSize);
-                } else {
-                    fragLen = Record.maxDataSize;
-                }
+    @Override
+    public synchronized void flush() throws IOException {
+        int position = headerSize + writeCipher.getExplicitNonceSize();
+        if (count <= position) {
+            return;
+        }
 
-                if (fragmentSize > 0) {
-                    fragLen = Math.min(fragLen, fragmentSize);
-                }
+        if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+            SSLLogger.fine(
+                    "WRITE: " + protocolVersion +
+                    " " + ContentType.HANDSHAKE.name +
+                    ", length = " + (count - headerSize));
+        }
 
-                if (isFirstRecordOfThePayload && needToSplitPayload()) {
-                    fragLen = 1;
-                    isFirstRecordOfThePayload = false;
-                } else {
-                    fragLen = Math.min(fragLen, (limit - offset));
-                }
+        // Encrypt the fragment and wrap up a record.
+        encrypt(writeCipher, ContentType.HANDSHAKE.id, headerSize);
 
-                // use the buf of ByteArrayOutputStream
-                int position = headerSize + writeCipher.getExplicitNonceSize();
-                count = position;
-                write(source, offset, fragLen);
+        // deliver this message
+        deliverStream.write(buf, 0, count);    // may throw IOException
+        deliverStream.flush();                 // may throw IOException
+
+        if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+            SSLLogger.fine("Raw write",
+                    (new ByteArrayInputStream(buf, 0, count)));
+        }
 
-                if (SSLLogger.isOn && SSLLogger.isOn("record")) {
-                    SSLLogger.fine(
-                            "WRITE: " + protocolVersion +
-                            " " + ContentType.APPLICATION_DATA.name +
-                            ", length = " + (count - position));
-                }
+        // reset the internal buffer
+        count = 0;      // DON'T use position
+    }
 
-                // Encrypt the fragment and wrap up a record.
-                encrypt(writeCipher,
-                        ContentType.APPLICATION_DATA.id, headerSize);
+    @Override
+    synchronized void deliver(
+            byte[] source, int offset, int length) throws IOException {
+        if (isClosed()) {
+            throw new SocketException("Connection or outbound has been closed");
+        }
 
-                // deliver this message
-                deliverStream.write(buf, 0, count);    // may throw IOException
-                deliverStream.flush();                 // may throw IOException
+        if (writeCipher.authenticator.seqNumOverflow()) {
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                SSLLogger.fine(
+                    "sequence number extremely close to overflow " +
+                    "(2^64-1 packets). Closing connection.");
+            }
 
-                if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
-                    SSLLogger.fine("Raw write",
-                            (new ByteArrayInputStream(buf, 0, count)));
-                }
+            throw new SSLHandshakeException("sequence number overflow");
+        }
 
-                // reset the internal buffer
-                count = 0;
+        boolean isFirstRecordOfThePayload = true;
+        for (int limit = (offset + length); offset < limit;) {
+            int fragLen;
+            if (packetSize > 0) {
+                fragLen = Math.min(maxRecordSize, packetSize);
+                fragLen =
+                        writeCipher.calculateFragmentSize(fragLen, headerSize);
+
+                fragLen = Math.min(fragLen, Record.maxDataSize);
+            } else {
+                fragLen = Record.maxDataSize;
+            }
+
+            if (fragmentSize > 0) {
+                fragLen = Math.min(fragLen, fragmentSize);
+            }
+
+            if (isFirstRecordOfThePayload && needToSplitPayload()) {
+                fragLen = 1;
+                isFirstRecordOfThePayload = false;
+            } else {
+                fragLen = Math.min(fragLen, (limit - offset));
+            }
 
-                if (isFirstAppOutputRecord) {
-                    isFirstAppOutputRecord = false;
-                }
+            // use the buf of ByteArrayOutputStream
+            int position = headerSize + writeCipher.getExplicitNonceSize();
+            count = position;
+            write(source, offset, fragLen);
 
-                offset += fragLen;
+            if (SSLLogger.isOn && SSLLogger.isOn("record")) {
+                SSLLogger.fine(
+                        "WRITE: " + protocolVersion +
+                        " " + ContentType.APPLICATION_DATA.name +
+                        ", length = " + (count - position));
             }
-        } finally {
-            recordLock.unlock();
+
+            // Encrypt the fragment and wrap up a record.
+            encrypt(writeCipher, ContentType.APPLICATION_DATA.id, headerSize);
+
+            // deliver this message
+            deliverStream.write(buf, 0, count);    // may throw IOException
+            deliverStream.flush();                 // may throw IOException
+
+            if (SSLLogger.isOn && SSLLogger.isOn("packet")) {
+                SSLLogger.fine("Raw write",
+                        (new ByteArrayInputStream(buf, 0, count)));
+            }
+
+            // reset the internal buffer
+            count = 0;
+
+            if (isFirstAppOutputRecord) {
+                isFirstAppOutputRecord = false;
+            }
+
+            offset += fragLen;
         }
     }
 
     @Override
-    void setDeliverStream(OutputStream outputStream) {
-        recordLock.lock();
-        try {
-            this.deliverStream = outputStream;
-        } finally {
-            recordLock.unlock();
-        }
+    synchronized void setDeliverStream(OutputStream outputStream) {
+        this.deliverStream = outputStream;
     }
 
     /*
      * Need to split the payload except the following cases:
      *
< prev index next >