diff --git a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java b/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java index 6c1ff357b6..aca30deb8c 100644 --- a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoder.java @@ -16,6 +16,7 @@ package org.jboss.netty.handler.codec.spdy; import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; import static org.jboss.netty.handler.codec.spdy.SpdyCodecUtil.*; @@ -27,6 +28,8 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { private State state; + private ChannelBuffer cumulation; + private int headerSize; private int numHeaders; private int length; @@ -67,6 +70,24 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { throw new NullPointerException("frame"); } + if (cumulation == null) { + decodeHeaderBlock(headerBlock, frame); + if (headerBlock.readable()) { + cumulation = ChannelBuffers.dynamicBuffer(headerBlock.readableBytes()); + cumulation.writeBytes(headerBlock); + } + } else { + cumulation.writeBytes(headerBlock); + decodeHeaderBlock(cumulation, frame); + if (cumulation.readable()) { + cumulation.discardReadBytes(); + } else { + cumulation = null; + } + } + } + + protected void decodeHeaderBlock(ChannelBuffer headerBlock, SpdyHeadersFrame frame) throws Exception { int skipLength; while (headerBlock.readable()) { switch(state) { @@ -267,6 +288,9 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { if (state != State.END_HEADER_BLOCK) { frame.setInvalid(); } + + cumulation = null; + // Initialize header block decoding fields headerSize = 0; name = null; @@ -275,5 +299,6 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder { @Override void end() { + cumulation = null; } } diff --git a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java b/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java index 6e1da0a4d3..9824d9c90a 100644 --- a/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoder.java @@ -93,7 +93,7 @@ final class SpdyHeaderBlockZlibDecoder extends SpdyHeaderBlockRawDecoder { } decompressed.writerIndex(decompressed.writerIndex() + numBytes); - super.decode(decompressed, frame); + super.decodeHeaderBlock(decompressed, frame); decompressed.discardReadBytes(); return numBytes; diff --git a/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java b/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java index a10888086e..4249aab2fc 100644 --- a/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java +++ b/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockRawDecoderTest.java @@ -391,25 +391,21 @@ public class SpdyHeaderBlockRawDecoderTest { @Test public void testMultipleDecodes() throws Exception { - ChannelBuffer numHeaders = ChannelBuffers.buffer(4); - numHeaders.writeInt(1); + ChannelBuffer headerBlock = ChannelBuffers.buffer(21); + headerBlock.writeInt(1); + headerBlock.writeInt(4); + headerBlock.writeBytes(nameBytes); + headerBlock.writeInt(5); + headerBlock.writeBytes(valueBytes); - ChannelBuffer nameBlock = ChannelBuffers.buffer(8); - nameBlock.writeInt(4); - nameBlock.writeBytes(nameBytes); - - ChannelBuffer valueBlock = ChannelBuffers.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++) { + ChannelBuffer headerBlockSegment = headerBlock.slice(i, 1); + decoder.decode(headerBlockSegment, frame); + assertFalse(headerBlockSegment.readable()); + } decoder.endHeaderBlock(frame); - assertFalse(numHeaders.readable()); - assertFalse(nameBlock.readable()); - assertFalse(valueBlock.readable()); assertFalse(frame.isInvalid()); assertEquals(1, frame.headers().names().size()); assertTrue(frame.headers().contains(name)); diff --git a/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java b/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java index 9ccbf405c1..582cf879f0 100644 --- a/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java +++ b/src/test/java/org/jboss/netty/handler/codec/spdy/SpdyHeaderBlockZlibDecoderTest.java @@ -92,6 +92,7 @@ public class SpdyHeaderBlockZlibDecoderTest { for (int i = 0; i < readableBytes; i++) { ChannelBuffer headerBlockSegment = headerBlock.slice(i, 1); decoder.decode(headerBlockSegment, frame); + assertFalse(headerBlockSegment.readable()); } decoder.endHeaderBlock(frame);