diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java index a91f0b7784..d0fa052cd3 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java @@ -27,6 +27,8 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { private State state; + private ByteBuf cumulation; + private int headerSize; private int numHeaders; private int length; @@ -67,6 +69,24 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { throw new NullPointerException("frame"); } + if (cumulation == null) { + decodeHeaderBlock(headerBlock, frame); + if (headerBlock.isReadable()) { + cumulation = headerBlock.alloc().buffer(headerBlock.readableBytes()); + cumulation.writeBytes(headerBlock); + } + } else { + cumulation.writeBytes(headerBlock); + decodeHeaderBlock(cumulation, frame); + if (cumulation.isReadable()) { + cumulation.discardReadBytes(); + } else { + cumulation = null; + } + } + } + + protected void decodeHeaderBlock(ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { int skipLength; while (headerBlock.isReadable()) { switch(state) { @@ -267,6 +287,9 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { if (state != State.END_HEADER_BLOCK) { frame.setInvalid(); } + + releaseBuffer(); + // Initialize header block decoding fields headerSize = 0; name = null; @@ -275,5 +298,13 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { @Override void end() { + releaseBuffer(); + } + + private void releaseBuffer() { + if (cumulation != null) { + cumulation.release(); + cumulation = null; + } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java index 476aa6bf27..dffa26b163 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java @@ -86,7 +86,7 @@ final class SpdyHeaderBlockZlibDecoder extends SpdyHeaderBlockRawDecoder { } if (frame != null) { decompressed.writerIndex(decompressed.writerIndex() + numBytes); - super.decode(decompressed, frame); + super.decodeHeaderBlock(decompressed, frame); decompressed.discardReadBytes(); } diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java index 1436dfa534..754aca58bb 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java @@ -391,25 +391,21 @@ public class SpdyHeaderBlockRawDecoderTest { @Test public void testMultipleDecodes() throws Exception { - ByteBuf numHeaders = Unpooled.buffer(4); - numHeaders.writeInt(1); + ByteBuf headerBlock = Unpooled.buffer(21); + headerBlock.writeInt(1); + headerBlock.writeInt(4); + headerBlock.writeBytes(nameBytes); + headerBlock.writeInt(5); + headerBlock.writeBytes(valueBytes); - ByteBuf nameBlock = Unpooled.buffer(8); - nameBlock.writeInt(4); - nameBlock.writeBytes(nameBytes); - - ByteBuf valueBlock = Unpooled.buffer(9); - valueBlock.writeInt(5); - valueBlock.writeBytes(valueBytes); - - decoder.decode(numHeaders, frame); - decoder.decode(nameBlock, frame); - decoder.decode(valueBlock, frame); + int readableBytes = headerBlock.readableBytes(); + for (int i = 0; i < readableBytes; i++) { + ByteBuf headerBlockSegment = headerBlock.slice(i, 1); + decoder.decode(headerBlockSegment, frame); + assertFalse(headerBlockSegment.isReadable()); + } decoder.endHeaderBlock(frame); - assertFalse(numHeaders.isReadable()); - assertFalse(nameBlock.isReadable()); - assertFalse(valueBlock.isReadable()); assertFalse(frame.isInvalid()); assertEquals(1, frame.headers().names().size()); assertTrue(frame.headers().contains(name)); diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java index 49e049d6dc..4a9efa32a9 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java @@ -92,6 +92,7 @@ public class SpdyHeaderBlockZlibDecoderTest { for (int i = 0; i < readableBytes; i++) { ByteBuf headerBlockSegment = headerBlock.slice(i, 1); decoder.decode(headerBlockSegment, frame); + assertFalse(headerBlockSegment.isReadable()); } decoder.endHeaderBlock(frame);