SPDY: ensure SpdyHeaderBlockRawDecoder always reads entire input

This commit is contained in:
Jeff Pinner 2014-05-04 15:18:34 -07:00 committed by Norman Maurer
parent 00bf5eb898
commit b58277e079
4 changed files with 39 additions and 17 deletions

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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));

View File

@ -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);