From 60acd54c7efb2385ab7488f69c5b62c2e1a33183 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Tue, 1 Oct 2013 10:20:01 +0200 Subject: [PATCH] [#1876] Make use of proper state machine in WebSocket08FrameDecoder for performance reasons --- .../websocketx/WebSocket00FrameDecoder.java | 9 +- .../websocketx/WebSocket08FrameDecoder.java | 313 ++++++++---------- 2 files changed, 142 insertions(+), 180 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java index f88229fcdf..11263531a4 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java @@ -22,6 +22,8 @@ import io.netty.handler.codec.TooLongFrameException; import java.util.List; +import static io.netty.buffer.ByteBufUtil.readBytes; + /** * Decodes {@link ByteBuf}s into {@link WebSocketFrame}s. *

@@ -91,8 +93,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder implements W receivedClosingHandshake = true; return new CloseWebSocketFrame(); } - ByteBuf payload = ctx.alloc().buffer((int) frameSize); - buffer.readBytes(payload); + ByteBuf payload = readBytes(ctx.alloc(), buffer, (int) frameSize); return new BinaryWebSocketFrame(payload); } @@ -116,12 +117,12 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder implements W throw new TooLongFrameException(); } - ByteBuf binaryData = ctx.alloc().buffer(frameSize); - buffer.readBytes(binaryData); + ByteBuf binaryData = readBytes(ctx.alloc(), buffer, frameSize); buffer.skipBytes(1); int ffDelimPos = binaryData.indexOf(binaryData.readerIndex(), binaryData.writerIndex(), (byte) 0xFF); if (ffDelimPos >= 0) { + binaryData.release(); throw new IllegalArgumentException("a text frame should not contain 0xFF."); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java index e34a3a2dc4..79a1aa5759 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java @@ -57,21 +57,32 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; -import io.netty.handler.codec.ReplayingDecoder; import io.netty.handler.codec.TooLongFrameException; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.util.List; +import static io.netty.buffer.ByteBufUtil.readBytes; + /** * Decodes a web socket frame from wire protocol version 8 format. This code was forked from webbit and modified. */ -public class WebSocket08FrameDecoder extends ReplayingDecoder +public class WebSocket08FrameDecoder extends ByteToMessageDecoder implements WebSocketFrameDecoder { + enum State { + READING_FIRST, + READING_SECOND, + READING_SIZE, + MASKING_KEY, + PAYLOAD, + CORRUPT + } + private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocket08FrameDecoder.class); private static final byte OPCODE_CONT = 0x0; @@ -83,24 +94,19 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder 0) { - payloadBuffer.release(); - } - payloadBuffer = null; - } - if (framePayload != null) { - if (framePayload.refCnt() > 0) { - framePayload.release(); - } - framePayload = null; - } - throw e; - } } private void unmask(ByteBuf frame) { @@ -413,7 +388,7 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder