You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/06/24 14:31:33 UTC

svn commit: r1605066 - in /tomcat/trunk/java/org/apache/tomcat/websocket: PerMessageDeflate.java Transformation.java WsFrameBase.java

Author: markt
Date: Tue Jun 24 12:31:32 2014
New Revision: 1605066

URL: http://svn.apache.org/r1605066
Log:
Handle decompression for messages split across multiple frames.

Modified:
    tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
    tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java
    tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java?rev=1605066&r1=1605065&r2=1605066&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java Tue Jun 24 12:31:32 2014
@@ -48,6 +48,7 @@ public class PerMessageDeflate implement
     private final ByteBuffer readBuffer = ByteBuffer.allocate(8192);
 
     private Transformation next;
+    private boolean skipDecompression = false;
 
     PerMessageDeflate(List<Parameter> params) {
 
@@ -89,12 +90,23 @@ public class PerMessageDeflate implement
     }
 
     @Override
-    public TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer dest) throws IOException {
+    public TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest)
+            throws IOException {
 
-        // Control frames are never compressed. Pass control frames and
-        // uncompressed frames straight through.
-        if (Util.isControl(opCode) || (rsv & RSV_BITMASK) == 0) {
-            return next.getMoreData(opCode, rsv, dest);
+        // Control frames are never compressed and may appear in the middle of
+        // a WebSocket method. Pass them straight through.
+        if (Util.isControl(opCode)) {
+            return next.getMoreData(opCode, fin, rsv, dest);
+        }
+
+        if (!Util.isContinuation(opCode)) {
+            // First frame in new message
+            skipDecompression = (rsv & RSV_BITMASK) == 0;
+        }
+
+        // Pass uncompressed frames straight through.
+        if (skipDecompression) {
+            return next.getMoreData(opCode, fin, rsv, dest);
         }
 
         int written;
@@ -114,15 +126,19 @@ public class PerMessageDeflate implement
                 if (dest.hasRemaining()) {
                     readBuffer.clear();
                     TransformationResult nextResult =
-                            next.getMoreData(opCode, (rsv ^ RSV_BITMASK), readBuffer);
+                            next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer);
                     inflator.setInput(
                             readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position());
                     if (TransformationResult.UNDERFLOW.equals(nextResult)) {
                         return nextResult;
                     } else if (TransformationResult.END_OF_FRAME.equals(nextResult) &&
                             readBuffer.position() == 0) {
-                        inflator.setInput(EOM_BYTES);
-                        usedEomBytes = true;
+                        if (fin) {
+                            inflator.setInput(EOM_BYTES);
+                            usedEomBytes = true;
+                        } else {
+                            return TransformationResult.END_OF_FRAME;
+                        }
                     }
                 }
             } else if (written == 0) {

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java?rev=1605066&r1=1605065&r2=1605066&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/Transformation.java Tue Jun 24 12:31:32 2014
@@ -33,11 +33,12 @@ public interface Transformation {
      * Obtain more input data.
      *
      * @param opCode    The opcode for the frame currently being processed
+     * @param fin       Is this the final frame in this WebSocket message?
      * @param rsv       The reserved bits for the frame currently being
      *                      processed
      * @param dest      The buffer in which the data is to be written
      */
-    TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer dest) throws IOException;
+    TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest) throws IOException;
 
     /**
      * Validates the RSV and opcode combination (assumed to have been extracted

Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java?rev=1605066&r1=1605065&r2=1605066&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java Tue Jun 24 12:31:32 2014
@@ -300,7 +300,7 @@ public abstract class WsFrameBase {
 
 
     private boolean processDataControl() throws IOException {
-        TransformationResult tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
+        TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         if (TransformationResult.UNDERFLOW.equals(tr)) {
             return false;
         }
@@ -402,7 +402,7 @@ public abstract class WsFrameBase {
 
     private boolean processDataText() throws IOException {
         // Copy the available data to the buffer
-        TransformationResult tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
+        TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         while (!TransformationResult.END_OF_FRAME.equals(tr)) {
             // Frame not complete - we ran out of something
             // Convert bytes to UTF-8
@@ -443,7 +443,7 @@ public abstract class WsFrameBase {
                 }
             }
             // Read more input data
-            tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
+            tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         }
 
         messageBufferBinary.flip();
@@ -501,7 +501,7 @@ public abstract class WsFrameBase {
 
     private boolean processDataBinary() throws IOException {
         // Copy the available data to the buffer
-        TransformationResult tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
+        TransformationResult tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         while (!TransformationResult.END_OF_FRAME.equals(tr)) {
             // Frame not complete - what did we run out of?
             if (TransformationResult.UNDERFLOW.equals(tr)) {
@@ -526,7 +526,7 @@ public abstract class WsFrameBase {
             sendMessageBinary(copy, false);
             messageBufferBinary.clear();
             // Read more data
-            tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
+            tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         }
 
         // Frame is fully received
@@ -735,7 +735,8 @@ public abstract class WsFrameBase {
     private final class NoopTransformation extends TerminalTransformation {
 
         @Override
-        public TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer dest) {
+        public TransformationResult getMoreData(byte opCode, boolean fin, int rsv,
+                ByteBuffer dest) {
             // opCode is ignored as the transformation is the same for all
             // opCodes
             // rsv is ignored as it known to be zero at this point
@@ -766,7 +767,8 @@ public abstract class WsFrameBase {
     private final class UnmaskTransformation extends TerminalTransformation {
 
         @Override
-        public TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer dest) {
+        public TransformationResult getMoreData(byte opCode, boolean fin, int rsv,
+                ByteBuffer dest) {
             // opCode is ignored as the transformation is the same for all
             // opCodes
             // rsv is ignored as it known to be zero at this point



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