Author: violetagg
Date: Tue Sep 16 20:15:51 2014
New Revision: 1625372

URL: http://svn.apache.org/r1625372
Log:
Merged revision 1605054 from tomcat/trunk:
Refactor transformations to enable the handing of overflow (the previous code 
ignored this possibility).

Added:
    
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/TransformationResult.java
      - copied unchanged from r1605054, 
tomcat/trunk/java/org/apache/tomcat/websocket/TransformationResult.java
Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Transformation.java
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1605054

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java?rev=1625372&r1=1625371&r2=1625372&view=diff
==============================================================================
--- 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java 
(original)
+++ 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/PerMessageDeflate.java 
Tue Sep 16 20:15:51 2014
@@ -89,41 +89,51 @@ public class PerMessageDeflate implement
     }
 
     @Override
-    public boolean getMoreData(byte opCode, int rsv, ByteBuffer dest) throws 
IOException {
+    public TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer 
dest) throws IOException {
 
-        // Control frames are never compressed
+        // 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);
         }
 
-        boolean endOfInputFrame = false;
+        int written;
+        boolean usedEomBytes = false;
 
-        if (inflator.needsInput()) {
-            readBuffer.clear();
-            endOfInputFrame = next.getMoreData(opCode, (rsv ^ RSV_BITMASK), 
readBuffer);
-            inflator.setInput(readBuffer.array(), readBuffer.arrayOffset(), 
readBuffer.position());
-        }
-
-        int written = 0;
-        try {
-            written = inflator.inflate(dest.array(), dest.arrayOffset() + 
dest.position(), dest.remaining());
-            if (endOfInputFrame && !inflator.finished()) {
-                inflator.setInput(EOM_BYTES);
-                inflator.inflate(dest.array(), dest.arrayOffset() + 
dest.position(), dest.remaining());
+        while (dest.remaining() > 0) {
+            // Space available in destination. Try and fill it.
+            try {
+                written = inflator.inflate(
+                        dest.array(), dest.arrayOffset() + dest.position(), 
dest.remaining());
+            } catch (DataFormatException e) {
+                throw new 
IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
             }
-        } catch (DataFormatException e) {
-            throw new 
IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
-        }
-        dest.position(dest.position() + written);
-
+            dest.position(dest.position() + written);
 
-        if (endOfInputFrame && !clientContextTakeover) {
-            inflator.reset();
+            if (inflator.needsInput() && !usedEomBytes ) {
+                if (dest.hasRemaining()) {
+                    readBuffer.clear();
+                    TransformationResult nextResult =
+                            next.getMoreData(opCode, (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;
+                    }
+                }
+            } else if (written == 0) {
+                return TransformationResult.END_OF_FRAME;
+            }
         }
 
-        return endOfInputFrame;
+        return TransformationResult.OVERFLOW;
     }
 
+
     @Override
     public boolean validateRsv(int rsv, byte opCode) {
         if (Util.isControl(opCode)) {

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Transformation.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Transformation.java?rev=1625372&r1=1625371&r2=1625372&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Transformation.java 
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Transformation.java 
Tue Sep 16 20:15:51 2014
@@ -36,11 +36,8 @@ public interface Transformation {
      * @param rsv       The reserved bits for the frame currently being
      *                      processed
      * @param dest      The buffer in which the data is to be written
-     *
-     * @return <code>true</code> if the data source has been fully read
-     *         otherwise <code>false</code>
      */
-    boolean getMoreData(byte opCode, int rsv, ByteBuffer dest) throws 
IOException;
+    TransformationResult getMoreData(byte opCode, int rsv, ByteBuffer dest) 
throws IOException;
 
     /**
      * Validates the RSV and opcode combination (assumed to have been extracted

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java?rev=1625372&r1=1625371&r2=1625372&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java 
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/WsFrameBase.java Tue 
Sep 16 20:15:51 2014
@@ -300,9 +300,13 @@ public abstract class WsFrameBase {
 
 
     private boolean processDataControl() throws IOException {
-        if (!transformation.getMoreData(opCode, rsv, controlBufferBinary)) {
+        TransformationResult tr = transformation.getMoreData(opCode, rsv, 
messageBufferBinary);
+        if (TransformationResult.UNDERFLOW.equals(tr)) {
             return false;
         }
+        // Control messages have fixed message size so
+        // TransformationResult.OVERFLOW is not possible here
+
         controlBufferBinary.flip();
         if (opCode == Constants.OPCODE_CLOSE) {
             open = false;
@@ -398,7 +402,8 @@ public abstract class WsFrameBase {
 
     private boolean processDataText() throws IOException {
         // Copy the available data to the buffer
-        while (!transformation.getMoreData(opCode, rsv, messageBufferBinary)) {
+        TransformationResult tr = transformation.getMoreData(opCode, rsv, 
messageBufferBinary);
+        while (!TransformationResult.END_OF_FRAME.equals(tr)) {
             // Frame not complete - we ran out of something
             // Convert bytes to UTF-8
             messageBufferBinary.flip();
@@ -421,21 +426,24 @@ public abstract class WsFrameBase {
                                 sm.getString("wsFrame.textMessageTooBig")));
                     }
                 } else if (cr.isUnderflow()) {
-                    // Need more input
                     // Compact what we have to create as much space as possible
                     messageBufferBinary.compact();
 
+                    // Need more input
                     // What did we run out of?
-                    if (readPos == writePos) {
-                        // Ran out of input data - get some more
-                        return false;
-                    } else {
+                    if (TransformationResult.OVERFLOW.equals(tr)) {
                         // Ran out of message buffer - exit inner loop and
                         // refill
                         break;
+                    } else {
+                        // TransformationResult.UNDERFLOW
+                        // Ran out of input data - get some more
+                        return false;
                     }
                 }
             }
+            // Read more input data
+            tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
         }
 
         messageBufferBinary.flip();
@@ -493,29 +501,32 @@ public abstract class WsFrameBase {
 
     private boolean processDataBinary() throws IOException {
         // Copy the available data to the buffer
-        while (!transformation.getMoreData(opCode, rsv, messageBufferBinary)) {
+        TransformationResult tr = transformation.getMoreData(opCode, rsv, 
messageBufferBinary);
+        while (!TransformationResult.END_OF_FRAME.equals(tr)) {
             // Frame not complete - what did we run out of?
-            if (readPos == writePos) {
+            if (TransformationResult.UNDERFLOW.equals(tr)) {
                 // Ran out of input data - get some more
                 return false;
-            } else {
-                // Ran out of message buffer - flush it
-                if (!usePartial()) {
-                    CloseReason cr = new CloseReason(CloseCodes.TOO_BIG,
-                            sm.getString("wsFrame.bufferTooSmall",
-                                    Integer.valueOf(
-                                            messageBufferBinary.capacity()),
-                                    Long.valueOf(payloadLength)));
-                    throw new WsIOException(cr);
-                }
-                messageBufferBinary.flip();
-                ByteBuffer copy =
-                        ByteBuffer.allocate(messageBufferBinary.limit());
-                copy.put(messageBufferBinary);
-                copy.flip();
-                sendMessageBinary(copy, false);
-                messageBufferBinary.clear();
             }
+
+            // Ran out of message buffer - flush it
+            if (!usePartial()) {
+                CloseReason cr = new CloseReason(CloseCodes.TOO_BIG,
+                        sm.getString("wsFrame.bufferTooSmall",
+                                Integer.valueOf(
+                                        messageBufferBinary.capacity()),
+                                Long.valueOf(payloadLength)));
+                throw new WsIOException(cr);
+            }
+            messageBufferBinary.flip();
+            ByteBuffer copy =
+                    ByteBuffer.allocate(messageBufferBinary.limit());
+            copy.put(messageBufferBinary);
+            copy.flip();
+            sendMessageBinary(copy, false);
+            messageBufferBinary.clear();
+            // Read more data
+            tr = transformation.getMoreData(opCode, rsv, messageBufferBinary);
         }
 
         // Frame is fully received
@@ -724,7 +735,7 @@ public abstract class WsFrameBase {
     private final class NoopTransformation extends TerminalTransformation {
 
         @Override
-        public boolean getMoreData(byte opCode, int rsv, ByteBuffer dest) {
+        public TransformationResult getMoreData(byte opCode, 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
@@ -735,7 +746,15 @@ public abstract class WsFrameBase {
             dest.put(inputBuffer, readPos, (int) toWrite);
             readPos += toWrite;
             payloadWritten += toWrite;
-            return (payloadWritten == payloadLength);
+
+            if (payloadWritten == payloadLength) {
+                return TransformationResult.END_OF_FRAME;
+            } else if (readPos == writePos) {
+                return TransformationResult.UNDERFLOW;
+            } else {
+                // !dest.hasRemaining()
+                return TransformationResult.OVERFLOW;
+            }
         }
     }
 
@@ -747,7 +766,7 @@ public abstract class WsFrameBase {
     private final class UnmaskTransformation extends TerminalTransformation {
 
         @Override
-        public boolean getMoreData(byte opCode, int rsv, ByteBuffer dest) {
+        public TransformationResult getMoreData(byte opCode, 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
@@ -762,7 +781,14 @@ public abstract class WsFrameBase {
                 payloadWritten++;
                 dest.put(b);
             }
-            return (payloadWritten == payloadLength);
+            if (payloadWritten == payloadLength) {
+                return TransformationResult.END_OF_FRAME;
+            } else if (readPos == writePos) {
+                return TransformationResult.UNDERFLOW;
+            } else {
+                // !dest.hasRemaining()
+                return TransformationResult.OVERFLOW;
+            }
         }
     }
 }



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

Reply via email to