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: [email protected]
For additional commands, e-mail: [email protected]