[#1352] WebSocketFrameAggregator should only throw TooLongFrameException once per complete frame

This commit is contained in:
Norman Maurer 2013-05-09 21:12:36 +02:00
parent c8de4f03f1
commit 3268d6fc2e
2 changed files with 28 additions and 1 deletions

View File

@ -31,6 +31,7 @@ import io.netty.handler.codec.TooLongFrameException;
public class WebSocketFrameAggregator extends MessageToMessageDecoder<WebSocketFrame> { public class WebSocketFrameAggregator extends MessageToMessageDecoder<WebSocketFrame> {
private final int maxFrameSize; private final int maxFrameSize;
private WebSocketFrame currentFrame; private WebSocketFrame currentFrame;
private boolean tooLongFrameFound;
/** /**
* Construct a new instance * Construct a new instance
@ -48,6 +49,7 @@ public class WebSocketFrameAggregator extends MessageToMessageDecoder<WebSocketF
@Override @Override
protected void decode(ChannelHandlerContext ctx, WebSocketFrame msg, MessageBuf<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, WebSocketFrame msg, MessageBuf<Object> out) throws Exception {
if (currentFrame == null) { if (currentFrame == null) {
tooLongFrameFound = false;
if (msg.isFinalFragment()) { if (msg.isFinalFragment()) {
out.add(msg.retain()); out.add(msg.retain());
return; return;
@ -66,8 +68,15 @@ public class WebSocketFrameAggregator extends MessageToMessageDecoder<WebSocketF
return; return;
} }
if (msg instanceof ContinuationWebSocketFrame) { if (msg instanceof ContinuationWebSocketFrame) {
if (tooLongFrameFound) {
if (msg.isFinalFragment()) {
currentFrame = null;
}
return;
}
CompositeByteBuf content = (CompositeByteBuf) currentFrame.content(); CompositeByteBuf content = (CompositeByteBuf) currentFrame.content();
if (content.readableBytes() > maxFrameSize - msg.content().readableBytes()) { if (content.readableBytes() > maxFrameSize - msg.content().readableBytes()) {
tooLongFrameFound = true;
throw new TooLongFrameException( throw new TooLongFrameException(
"WebSocketFrame length exceeded " + content + "WebSocketFrame length exceeded " + content +
" bytes."); " bytes.");

View File

@ -101,11 +101,29 @@ public class WebSocketFrameAggregatorTest {
Assert.assertNull(channel.readInbound()); Assert.assertNull(channel.readInbound());
} }
@Test(expected = TooLongFrameException.class) @Test
public void textFrameTooBig() { public void textFrameTooBig() {
EmbeddedMessageChannel channel = new EmbeddedMessageChannel(new WebSocketFrameAggregator(8)); EmbeddedMessageChannel channel = new EmbeddedMessageChannel(new WebSocketFrameAggregator(8));
channel.writeInbound(new BinaryWebSocketFrame(true, 1, content1.copy())); channel.writeInbound(new BinaryWebSocketFrame(true, 1, content1.copy()));
channel.writeInbound(new BinaryWebSocketFrame(false, 0, content1.copy())); channel.writeInbound(new BinaryWebSocketFrame(false, 0, content1.copy()));
try {
channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy()));
Assert.fail();
} catch (TooLongFrameException e) {
// expected
}
channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy())); channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy()));
channel.writeInbound(new ContinuationWebSocketFrame(true, 0, content2.copy()));
channel.writeInbound(new BinaryWebSocketFrame(true, 1, content1.copy()));
channel.writeInbound(new BinaryWebSocketFrame(false, 0, content1.copy()));
try {
channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy()));
Assert.fail();
} catch (TooLongFrameException e) {
// expected
}
channel.writeInbound(new ContinuationWebSocketFrame(false, 0, content2.copy()));
channel.writeInbound(new ContinuationWebSocketFrame(true, 0, content2.copy()));
} }
} }