jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java
changeset 12428 e9feb65d37fa
parent 11026 41ce4af91010
child 13370 785cedd026db
--- a/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Apr 11 07:26:35 2012 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Wed Apr 11 17:12:35 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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
@@ -374,6 +374,12 @@
      */
     private boolean isFirstAppOutputRecord = true;
 
+    /*
+     * If AppOutputStream needs to delay writes of small packets, we
+     * will use this to store the data until we actually do the write.
+     */
+    private ByteArrayOutputStream heldRecordBuffer = null;
+
     //
     // CONSTRUCTORS AND INITIALIZATION CODE
     //
@@ -654,13 +660,24 @@
     //
 
     /*
+     * AppOutputStream calls may need to buffer multiple outbound
+     * application packets.
+     *
+     * All other writeRecord() calls will not buffer, so do not hold
+     * these records.
+     */
+    void writeRecord(OutputRecord r) throws IOException {
+        writeRecord(r, false);
+    }
+
+    /*
      * Record Output. Application data can't be sent until the first
      * handshake establishes a session.
      *
      * NOTE:  we let empty records be written as a hook to force some
      * TCP-level activity, notably handshaking, to occur.
      */
-    void writeRecord(OutputRecord r) throws IOException {
+    void writeRecord(OutputRecord r, boolean holdRecord) throws IOException {
         /*
          * The loop is in case of HANDSHAKE --> ERROR transitions, etc
          */
@@ -731,7 +748,7 @@
                 try {
                     if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
                         try {
-                            writeRecordInternal(r);
+                            writeRecordInternal(r, holdRecord);
                         } finally {
                             writeLock.unlock();
                         }
@@ -779,7 +796,7 @@
             } else {
                 writeLock.lock();
                 try {
-                    writeRecordInternal(r);
+                    writeRecordInternal(r, holdRecord);
                 } finally {
                     writeLock.unlock();
                 }
@@ -787,11 +804,29 @@
         }
     }
 
-    private void writeRecordInternal(OutputRecord r) throws IOException {
+    private void writeRecordInternal(OutputRecord r,
+            boolean holdRecord) throws IOException {
+
         // r.compress(c);
         r.addMAC(writeMAC);
         r.encrypt(writeCipher);
-        r.write(sockOutput);
+
+        if (holdRecord) {
+            // If we were requested to delay the record due to possibility
+            // of Nagle's being active when finally got to writing, and
+            // it's actually not, we don't really need to delay it.
+            if (getTcpNoDelay()) {
+                holdRecord = false;
+            } else {
+                // We need to hold the record, so let's provide
+                // a per-socket place to do it.
+                if (heldRecordBuffer == null) {
+                    // Likely only need 37 bytes.
+                    heldRecordBuffer = new ByteArrayOutputStream(40);
+                }
+            }
+        }
+        r.write(sockOutput, holdRecord, heldRecordBuffer);
 
         /*
          * Check the sequence number state