SPDY: ensure SpdyHeaderBlockRawDecoder always reads entire input
This commit is contained in:
parent
fb87e2906a
commit
df9a26583b
@ -27,6 +27,8 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
|
|||||||
|
|
||||||
private State state;
|
private State state;
|
||||||
|
|
||||||
|
private ByteBuf cumulation;
|
||||||
|
|
||||||
private int headerSize;
|
private int headerSize;
|
||||||
private int numHeaders;
|
private int numHeaders;
|
||||||
private int length;
|
private int length;
|
||||||
@ -67,6 +69,24 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
|
|||||||
throw new NullPointerException("frame");
|
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;
|
int skipLength;
|
||||||
while (headerBlock.isReadable()) {
|
while (headerBlock.isReadable()) {
|
||||||
switch(state) {
|
switch(state) {
|
||||||
@ -267,6 +287,9 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
|
|||||||
if (state != State.END_HEADER_BLOCK) {
|
if (state != State.END_HEADER_BLOCK) {
|
||||||
frame.setInvalid();
|
frame.setInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
releaseBuffer();
|
||||||
|
|
||||||
// Initialize header block decoding fields
|
// Initialize header block decoding fields
|
||||||
headerSize = 0;
|
headerSize = 0;
|
||||||
name = null;
|
name = null;
|
||||||
@ -275,5 +298,13 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void end() {
|
void end() {
|
||||||
|
releaseBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseBuffer() {
|
||||||
|
if (cumulation != null) {
|
||||||
|
cumulation.release();
|
||||||
|
cumulation = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ final class SpdyHeaderBlockZlibDecoder extends SpdyHeaderBlockRawDecoder {
|
|||||||
}
|
}
|
||||||
if (frame != null) {
|
if (frame != null) {
|
||||||
decompressed.writerIndex(decompressed.writerIndex() + numBytes);
|
decompressed.writerIndex(decompressed.writerIndex() + numBytes);
|
||||||
super.decode(decompressed, frame);
|
super.decodeHeaderBlock(decompressed, frame);
|
||||||
decompressed.discardReadBytes();
|
decompressed.discardReadBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,25 +391,21 @@ public class SpdyHeaderBlockRawDecoderTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleDecodes() throws Exception {
|
public void testMultipleDecodes() throws Exception {
|
||||||
ByteBuf numHeaders = Unpooled.buffer(4);
|
ByteBuf headerBlock = Unpooled.buffer(21);
|
||||||
numHeaders.writeInt(1);
|
headerBlock.writeInt(1);
|
||||||
|
headerBlock.writeInt(4);
|
||||||
|
headerBlock.writeBytes(nameBytes);
|
||||||
|
headerBlock.writeInt(5);
|
||||||
|
headerBlock.writeBytes(valueBytes);
|
||||||
|
|
||||||
ByteBuf nameBlock = Unpooled.buffer(8);
|
int readableBytes = headerBlock.readableBytes();
|
||||||
nameBlock.writeInt(4);
|
for (int i = 0; i < readableBytes; i++) {
|
||||||
nameBlock.writeBytes(nameBytes);
|
ByteBuf headerBlockSegment = headerBlock.slice(i, 1);
|
||||||
|
decoder.decode(headerBlockSegment, frame);
|
||||||
ByteBuf valueBlock = Unpooled.buffer(9);
|
assertFalse(headerBlockSegment.isReadable());
|
||||||
valueBlock.writeInt(5);
|
}
|
||||||
valueBlock.writeBytes(valueBytes);
|
|
||||||
|
|
||||||
decoder.decode(numHeaders, frame);
|
|
||||||
decoder.decode(nameBlock, frame);
|
|
||||||
decoder.decode(valueBlock, frame);
|
|
||||||
decoder.endHeaderBlock(frame);
|
decoder.endHeaderBlock(frame);
|
||||||
|
|
||||||
assertFalse(numHeaders.isReadable());
|
|
||||||
assertFalse(nameBlock.isReadable());
|
|
||||||
assertFalse(valueBlock.isReadable());
|
|
||||||
assertFalse(frame.isInvalid());
|
assertFalse(frame.isInvalid());
|
||||||
assertEquals(1, frame.headers().names().size());
|
assertEquals(1, frame.headers().names().size());
|
||||||
assertTrue(frame.headers().contains(name));
|
assertTrue(frame.headers().contains(name));
|
||||||
|
@ -92,6 +92,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
|
|||||||
for (int i = 0; i < readableBytes; i++) {
|
for (int i = 0; i < readableBytes; i++) {
|
||||||
ByteBuf headerBlockSegment = headerBlock.slice(i, 1);
|
ByteBuf headerBlockSegment = headerBlock.slice(i, 1);
|
||||||
decoder.decode(headerBlockSegment, frame);
|
decoder.decode(headerBlockSegment, frame);
|
||||||
|
assertFalse(headerBlockSegment.isReadable());
|
||||||
}
|
}
|
||||||
decoder.endHeaderBlock(frame);
|
decoder.endHeaderBlock(frame);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user