You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2014/11/03 12:36:29 UTC

svn commit: r1636324 - in /tomcat/trunk: java/org/apache/coyote/ java/org/apache/coyote/ajp/ java/org/apache/coyote/http11/ java/org/apache/coyote/http11/upgrade/ java/org/apache/coyote/spdy/ webapps/docs/

Author: remm
Date: Mon Nov  3 11:36:28 2014
New Revision: 1636324

URL: http://svn.apache.org/r1636324
Log:
Allow HTTP upgrade process to complete without data corruption when additional content is sent along with the upgrade header.

Modified:
    tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
    tomcat/trunk/java/org/apache/coyote/InputBuffer.java
    tomcat/trunk/java/org/apache/coyote/Processor.java
    tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
    tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
    tomcat/trunk/java/org/apache/coyote/http11/AbstractInputBuffer.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Protocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
    tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioProcessor.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioServletInputStream.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2Processor.java
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/NioProcessor.java
    tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Mon Nov  3 11:36:28 2014
@@ -18,6 +18,7 @@ package org.apache.coyote;
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.nio.ByteBuffer;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
@@ -666,11 +667,13 @@ public abstract class AbstractProtocol<S
                         // Get the HTTP upgrade handler
                         HttpUpgradeHandler httpUpgradeHandler =
                                 processor.getHttpUpgradeHandler();
+                        // Retrieve leftover input
+                        ByteBuffer leftoverInput = processor.getLeftoverInput();
                         // Release the Http11 processor to be re-used
                         release(wrapper, processor, false, false);
                         // Create the upgrade processor
                         processor = createUpgradeProcessor(
-                                wrapper, httpUpgradeHandler);
+                                wrapper, leftoverInput, httpUpgradeHandler);
                         // Mark the connection as upgraded
                         wrapper.setUpgraded(true);
                         // Associate with the processor with the connection
@@ -776,7 +779,7 @@ public abstract class AbstractProtocol<S
                 Processor<S> processor, boolean socketClosing,
                 boolean addToPoller);
         protected abstract Processor<S> createUpgradeProcessor(
-                SocketWrapper<S> socket,
+                SocketWrapper<S> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeProcessor) throws IOException;
 
         protected void register(AbstractProcessor<S> processor) {

Modified: tomcat/trunk/java/org/apache/coyote/InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/InputBuffer.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/InputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/coyote/InputBuffer.java Mon Nov  3 11:36:28 2014
@@ -27,9 +27,6 @@ import org.apache.tomcat.util.buf.ByteCh
  *
  * This class is used only in the protocol implementation. All reading from
  * Tomcat ( or adapter ) should be done using Request.doRead().
- *
- *
- * @author Remy Maucherat
  */
 public interface InputBuffer {
 

Modified: tomcat/trunk/java/org/apache/coyote/Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/Processor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/Processor.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.concurrent.Executor;
 
 import javax.servlet.http.HttpUpgradeHandler;
@@ -54,4 +55,10 @@ public interface Processor<S> {
     void recycle(boolean socketClosing);
 
     void setSslSupport(SSLSupport sslSupport);
+
+    /**
+     * Allows retrieving additional input during the upgrade process
+     * @return leftover bytes
+     */
+    ByteBuffer getLeftoverInput();
 }

Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProcessor.java Mon Nov  3 11:36:28 2014
@@ -1084,6 +1084,12 @@ public abstract class AbstractAjpProcess
     }
 
 
+    @Override
+    public ByteBuffer getLeftoverInput() {
+        return null;
+    }
+
+
     /**
      * Get more request body data from the web server and store it in the
      * internal buffer.

Modified: tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Mon Nov  3 11:36:28 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.coyote.ajp;
 
+import java.nio.ByteBuffer;
+
 import javax.servlet.http.HttpUpgradeHandler;
 
 import org.apache.coyote.AbstractProtocol;
@@ -99,7 +101,7 @@ public abstract class AbstractAjpProtoco
         }
 
         @Override
-        protected P createUpgradeProcessor(SocketWrapper<S> socket,
+        protected P createUpgradeProcessor(SocketWrapper<S> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeHandler) {
             // TODO should fail - throw IOE
             return null;

Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Processor.java Mon Nov  3 11:36:28 2014
@@ -18,6 +18,7 @@ package org.apache.coyote.http11;
 
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.nio.ByteBuffer;
 import java.util.Locale;
 import java.util.StringTokenizer;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -1792,7 +1793,6 @@ public abstract class AbstractHttp11Proc
             SocketWrapper<S> socketWrapper);
 
 
-
     @Override
     public final void recycle(boolean isSocketClosing) {
         getAdapter().checkRecycled(request, response);
@@ -1813,4 +1813,11 @@ public abstract class AbstractHttp11Proc
     }
 
     protected abstract void recycleInternal();
+
+
+    @Override
+    public ByteBuffer getLeftoverInput() {
+        return inputBuffer.getLeftover();
+    }
+
 }

Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractInputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractInputBuffer.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractInputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractInputBuffer.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import org.apache.coyote.InputBuffer;
 import org.apache.coyote.Request;
@@ -390,6 +391,15 @@ public abstract class AbstractInputBuffe
         }
     }
 
+    ByteBuffer getLeftover() {
+        int available = lastValid - pos;
+        if (available > 0) {
+            return ByteBuffer.wrap(buf, pos, available);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Is standard Servlet blocking IO being used for input?
      */

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11AprProtocol.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import javax.servlet.http.HttpUpgradeHandler;
 
@@ -330,11 +331,11 @@ public class Http11AprProtocol extends A
 
         @Override
         protected Processor<Long> createUpgradeProcessor(
-                SocketWrapper<Long> socket,
+                SocketWrapper<Long> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeProcessor)
                 throws IOException {
-            return new AprProcessor(socket, httpUpgradeProcessor,
-                    (AprEndpoint) proto.endpoint,
+            return new AprProcessor(socket, leftoverInput,
+                    httpUpgradeProcessor, (AprEndpoint) proto.endpoint,
                     proto.getUpgradeAsyncWriteBufferSize());
         }
     }

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Protocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Nio2Protocol.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.ReadPendingException;
 
 import javax.net.ssl.SSLEngine;
@@ -257,11 +258,11 @@ public class Http11Nio2Protocol extends 
 
         @Override
         protected Processor<Nio2Channel> createUpgradeProcessor(
-                SocketWrapper<Nio2Channel> socket,
+                SocketWrapper<Nio2Channel> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeProcessor)
                 throws IOException {
-            return new Nio2Processor(proto.endpoint, socket, httpUpgradeProcessor,
-                    proto.getUpgradeAsyncWriteBufferSize());
+            return new Nio2Processor(proto.endpoint, socket, leftoverInput,
+                    httpUpgradeProcessor, proto.getUpgradeAsyncWriteBufferSize());
         }
 
         @Override

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProcessor.java Mon Nov  3 11:36:28 2014
@@ -557,4 +557,5 @@ public class Http11NioProcessor extends 
     public void setSslSupport(SSLSupport sslSupport) {
         this.sslSupport = sslSupport;
     }
+
 }

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11NioProtocol.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
 import java.util.Iterator;
 
@@ -289,10 +290,10 @@ public class Http11NioProtocol extends A
 
         @Override
         protected Processor<NioChannel> createUpgradeProcessor(
-                SocketWrapper<NioChannel> socket,
+                SocketWrapper<NioChannel> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeProcessor)
                 throws IOException {
-            return new NioProcessor(socket, httpUpgradeProcessor,
+            return new NioProcessor(socket, leftoverInput, httpUpgradeProcessor,
                     proto.getEndpoint().getSelectorPool(),
                     proto.getUpgradeAsyncWriteBufferSize());
         }

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java Mon Nov  3 11:36:28 2014
@@ -18,6 +18,7 @@ package org.apache.coyote.http11;
 
 import java.io.IOException;
 import java.net.Socket;
+import java.nio.ByteBuffer;
 
 import javax.servlet.http.HttpUpgradeHandler;
 
@@ -197,10 +198,10 @@ public class Http11Protocol extends Abst
 
         @Override
         protected Processor<Socket> createUpgradeProcessor(
-                SocketWrapper<Socket> socket,
+                SocketWrapper<Socket> socket, ByteBuffer leftoverInput,
                 HttpUpgradeHandler httpUpgradeProcessor)
                 throws IOException {
-            return new BioProcessor(socket, httpUpgradeProcessor,
+            return new BioProcessor(socket, leftoverInput, httpUpgradeProcessor,
                     proto.getUpgradeAsyncWriteBufferSize());
         }
 

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AbstractProcessor.java Mon Nov  3 11:36:28 2014
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11.upgrade;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.concurrent.Executor;
 
 import javax.servlet.ServletInputStream;
@@ -178,4 +179,9 @@ public abstract class AbstractProcessor<
     public final void setSslSupport(SSLSupport sslSupport) {
         // NOOP
     }
+
+    @Override
+    public ByteBuffer getLeftoverInput() {
+        return null;
+    }
 }

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprProcessor.java Mon Nov  3 11:36:28 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.coyote.http11.upgrade;
 
+import java.nio.ByteBuffer;
+
 import javax.servlet.http.HttpUpgradeHandler;
 
 import org.apache.juli.logging.Log;
@@ -32,11 +34,11 @@ public class AprProcessor extends Abstra
 
     private static final int INFINITE_TIMEOUT = -1;
 
-    public AprProcessor(SocketWrapper<Long> wrapper,
+    public AprProcessor(SocketWrapper<Long> wrapper, ByteBuffer leftoverInput,
             HttpUpgradeHandler httpUpgradeProcessor, AprEndpoint endpoint,
             int asyncWriteBufferSize) {
         super(httpUpgradeProcessor,
-                new AprServletInputStream(wrapper),
+                new AprServletInputStream(wrapper, leftoverInput),
                 new AprServletOutputStream(wrapper, asyncWriteBufferSize, endpoint));
 
         Socket.timeoutSet(wrapper.getSocket().longValue(), INFINITE_TIMEOUT);

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java Mon Nov  3 11:36:28 2014
@@ -18,6 +18,7 @@ package org.apache.coyote.http11.upgrade
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
 
@@ -34,13 +35,18 @@ public class AprServletInputStream exten
 
     private final SocketWrapper<Long> wrapper;
     private final long socket;
+    private ByteBuffer leftoverInput;
     private volatile boolean eagain = false;
     private volatile boolean closed = false;
 
 
-    public AprServletInputStream(SocketWrapper<Long> wrapper) {
+    public AprServletInputStream(SocketWrapper<Long> wrapper, ByteBuffer leftoverInput) {
         this.wrapper = wrapper;
         this.socket = wrapper.getSocket().longValue();
+        if (leftoverInput != null) {
+            this.leftoverInput = ByteBuffer.allocate(leftoverInput.remaining());
+            this.leftoverInput.put(leftoverInput);
+        }
     }
 
 
@@ -52,6 +58,17 @@ public class AprServletInputStream exten
             throw new IOException(sm.getString("apr.closed", Long.valueOf(socket)));
         }
 
+        if (leftoverInput != null) {
+            if (leftoverInput.remaining() < len) {
+                len = leftoverInput.remaining();
+            }
+            leftoverInput.get(b, off, len);
+            if (leftoverInput.remaining() == 0) {
+                leftoverInput = null;
+            }
+            return len;
+        }
+
         Lock readLock = wrapper.getBlockingStatusReadLock();
         WriteLock writeLock = wrapper.getBlockingStatusWriteLock();
 

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioProcessor.java Mon Nov  3 11:36:28 2014
@@ -18,6 +18,7 @@ package org.apache.coyote.http11.upgrade
 
 import java.io.IOException;
 import java.net.Socket;
+import java.nio.ByteBuffer;
 
 import javax.servlet.http.HttpUpgradeHandler;
 
@@ -33,10 +34,10 @@ public class BioProcessor extends Abstra
 
     private static final int INFINITE_TIMEOUT = 0;
 
-    public BioProcessor(SocketWrapper<Socket> wrapper,
+    public BioProcessor(SocketWrapper<Socket> wrapper, ByteBuffer leftoverInput,
             HttpUpgradeHandler httpUpgradeProcessor,
             int asyncWriteBufferSize) throws IOException {
-        super(httpUpgradeProcessor, new BioServletInputStream(wrapper),
+        super(httpUpgradeProcessor, new BioServletInputStream(wrapper, leftoverInput),
                 new BioServletOutputStream(wrapper, asyncWriteBufferSize));
 
         wrapper.getSocket().setSoTimeout(INFINITE_TIMEOUT);

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioServletInputStream.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioServletInputStream.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioServletInputStream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/BioServletInputStream.java Mon Nov  3 11:36:28 2014
@@ -19,22 +19,39 @@ package org.apache.coyote.http11.upgrade
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.Socket;
+import java.nio.ByteBuffer;
 
 import org.apache.tomcat.util.net.SocketWrapper;
 
 public class BioServletInputStream extends AbstractServletInputStream {
 
     private final InputStream inputStream;
+    private ByteBuffer leftoverInput;
 
-    public BioServletInputStream(SocketWrapper<Socket> wrapper)
+    public BioServletInputStream(SocketWrapper<Socket> wrapper, ByteBuffer leftoverInput)
             throws IOException {
         inputStream = wrapper.getSocket().getInputStream();
+        if (leftoverInput != null) {
+            this.leftoverInput = ByteBuffer.allocate(leftoverInput.remaining());
+            this.leftoverInput.put(leftoverInput);
+        }
     }
 
     @Override
     protected int doRead(boolean block, byte[] b, int off, int len)
             throws IOException {
-        return inputStream.read(b, off, len);
+        if (leftoverInput != null) {
+            if (leftoverInput.remaining() < len) {
+                len = leftoverInput.remaining();
+            }
+            leftoverInput.get(b, off, len);
+            if (leftoverInput.remaining() == 0) {
+                leftoverInput = null;
+            }
+            return len;
+        } else {
+            return inputStream.read(b, off, len);
+        }
     }
 
     @Override

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2Processor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2Processor.java Mon Nov  3 11:36:28 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.coyote.http11.upgrade;
 
+import java.nio.ByteBuffer;
+
 import javax.servlet.http.HttpUpgradeHandler;
 
 import org.apache.juli.logging.Log;
@@ -33,7 +35,7 @@ public class Nio2Processor extends Abstr
     private static final int INFINITE_TIMEOUT = -1;
 
     public Nio2Processor(AbstractEndpoint<Nio2Channel> endpoint,
-            SocketWrapper<Nio2Channel> wrapper,
+            SocketWrapper<Nio2Channel> wrapper, ByteBuffer leftoverInput,
             HttpUpgradeHandler httpUpgradeProcessor,
             int asyncWriteBufferSize) {
         super(httpUpgradeProcessor,
@@ -41,5 +43,8 @@ public class Nio2Processor extends Abstr
                 new Nio2ServletOutputStream(wrapper, asyncWriteBufferSize, endpoint));
 
         wrapper.setTimeout(INFINITE_TIMEOUT);
+        if (leftoverInput != null) {
+            wrapper.getSocket().getBufHandler().getReadBuffer().put(leftoverInput);
+        }
     }
 }

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/NioProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/NioProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/NioProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/NioProcessor.java Mon Nov  3 11:36:28 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.coyote.http11.upgrade;
 
+import java.nio.ByteBuffer;
+
 import javax.servlet.http.HttpUpgradeHandler;
 
 import org.apache.juli.logging.Log;
@@ -32,7 +34,7 @@ public class NioProcessor extends Abstra
 
     private static final int INFINITE_TIMEOUT = -1;
 
-    public NioProcessor(SocketWrapper<NioChannel> wrapper,
+    public NioProcessor(SocketWrapper<NioChannel> wrapper, ByteBuffer leftoverInput,
             HttpUpgradeHandler httpUpgradeProcessor, NioSelectorPool pool,
             int asyncWriteBufferSize) {
         super(httpUpgradeProcessor,
@@ -40,5 +42,15 @@ public class NioProcessor extends Abstra
                 new NioServletOutputStream(wrapper, asyncWriteBufferSize, pool));
 
         wrapper.setTimeout(INFINITE_TIMEOUT);
+        if (leftoverInput != null) {
+            ByteBuffer readBuffer = wrapper.getSocket().getBufHandler().getReadBuffer();
+            if (readBuffer.remaining() > 0) {
+                readBuffer.flip();
+            } else {
+                readBuffer.clear();
+            }
+            readBuffer.put(leftoverInput);
+            readBuffer.flip();
+        }
     }
 }

Modified: tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/spdy/SpdyProcessor.java Mon Nov  3 11:36:28 2014
@@ -19,6 +19,7 @@ package org.apache.coyote.spdy;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.InetAddress;
+import java.nio.ByteBuffer;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -534,6 +535,11 @@ public class SpdyProcessor<S> extends Ab
     }
 
     @Override
+    public ByteBuffer getLeftoverInput() {
+        return null;
+    }
+
+    @Override
     public SocketState upgradeDispatch(SocketStatus status) throws IOException {
         return null;
     }

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1636324&r1=1636323&r2=1636324&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Nov  3 11:36:28 2014
@@ -45,6 +45,14 @@
   issues to not "pop up" wrt. others).
 -->
 <section name="Tomcat 8.0.16 (markt)">
+  <subsection name="Coyote">
+    <changelog>
+      <fix>
+        Allow HTTP upgrade process to complete without data corruption when
+        additional content is sent along with the upgrade header. (remm)
+      </fix>
+    </changelog>
+  </subsection>
 </section>
 <section name="Tomcat 8.0.15 (markt)">
   <subsection name="Catalina">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org