Reduce memory copies in spdy compression implementation.

Motivation:

Currently we do more memory copies then needed.

Modification:

- Directly use heap buffers to reduce memory copy
- Correctly release buffers to fix buffer leak

Result:

Less memory copies and no leaks
This commit is contained in:
Norman Maurer 2014-06-25 21:16:27 +02:00
parent 1504d2044d
commit 65686b6c83
10 changed files with 131 additions and 83 deletions

View File

@ -150,7 +150,7 @@ public class SpdyFrameCodec extends ByteToMessageDecoder
} else if (msg instanceof SpdySynStreamFrame) { } else if (msg instanceof SpdySynStreamFrame) {
SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg; SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(spdySynStreamFrame); ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdySynStreamFrame);
try { try {
frame = spdyFrameEncoder.encodeSynStreamFrame( frame = spdyFrameEncoder.encodeSynStreamFrame(
ctx.alloc(), ctx.alloc(),
@ -169,7 +169,7 @@ public class SpdyFrameCodec extends ByteToMessageDecoder
} else if (msg instanceof SpdySynReplyFrame) { } else if (msg instanceof SpdySynReplyFrame) {
SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg; SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(spdySynReplyFrame); ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdySynReplyFrame);
try { try {
frame = spdyFrameEncoder.encodeSynReplyFrame( frame = spdyFrameEncoder.encodeSynReplyFrame(
ctx.alloc(), ctx.alloc(),
@ -223,7 +223,7 @@ public class SpdyFrameCodec extends ByteToMessageDecoder
} else if (msg instanceof SpdyHeadersFrame) { } else if (msg instanceof SpdyHeadersFrame) {
SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg; SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(spdyHeadersFrame); ByteBuf headerBlock = spdyHeaderBlockEncoder.encode(ctx.alloc(), spdyHeadersFrame);
try { try {
frame = spdyFrameEncoder.encodeHeadersFrame( frame = spdyFrameEncoder.encodeHeadersFrame(
ctx.alloc(), ctx.alloc(),
@ -324,7 +324,7 @@ public class SpdyFrameCodec extends ByteToMessageDecoder
@Override @Override
public void readHeaderBlock(ByteBuf headerBlock) { public void readHeaderBlock(ByteBuf headerBlock) {
try { try {
spdyHeaderBlockDecoder.decode(headerBlock, spdyHeadersFrame); spdyHeaderBlockDecoder.decode(ctx.alloc(), headerBlock, spdyHeadersFrame);
} catch (Exception e) { } catch (Exception e) {
ctx.fireExceptionCaught(e); ctx.fireExceptionCaught(e);
} finally { } finally {

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
abstract class SpdyHeaderBlockDecoder { abstract class SpdyHeaderBlockDecoder {
@ -28,13 +29,14 @@ abstract class SpdyHeaderBlockDecoder {
* If the header block is malformed, the Headers frame will be marked as invalid. * If the header block is malformed, the Headers frame will be marked as invalid.
* A stream error with status code PROTOCOL_ERROR must be issued in response to an invalid frame. * A stream error with status code PROTOCOL_ERROR must be issued in response to an invalid frame.
* *
* @param alloc the {@link ByteBufAllocator} which can be used to allocate new {@link ByteBuf}s
* @param headerBlock the HeaderBlock to decode * @param headerBlock the HeaderBlock to decode
* @param frame the Headers frame that receives the Name/Value pairs * @param frame the Headers frame that receives the Name/Value pairs
* @throws Exception If the header block is malformed in a way that prevents any future * @throws Exception If the header block is malformed in a way that prevents any future
* decoding of any other header blocks, an exception will be thrown. * decoding of any other header blocks, an exception will be thrown.
* A session error with status code PROTOCOL_ERROR must be issued. * A session error with status code PROTOCOL_ERROR must be issued.
*/ */
abstract void decode(ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception; abstract void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception;
abstract void endHeaderBlock(SpdyHeadersFrame frame) throws Exception; abstract void endHeaderBlock(SpdyHeadersFrame frame) throws Exception;

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
abstract class SpdyHeaderBlockEncoder { abstract class SpdyHeaderBlockEncoder {
@ -32,6 +33,6 @@ abstract class SpdyHeaderBlockEncoder {
} }
} }
abstract ByteBuf encode(SpdyHeadersFrame frame) throws Exception; abstract ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception;
abstract void end(); abstract void end();
} }

View File

@ -18,6 +18,7 @@ package io.netty.handler.codec.spdy;
import com.jcraft.jzlib.Deflater; import com.jcraft.jzlib.Deflater;
import com.jcraft.jzlib.JZlib; import com.jcraft.jzlib.JZlib;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.handler.codec.compression.CompressionException; import io.netty.handler.codec.compression.CompressionException;
@ -60,28 +61,52 @@ class SpdyHeaderBlockJZlibEncoder extends SpdyHeaderBlockRawEncoder {
} }
private void setInput(ByteBuf decompressed) { private void setInput(ByteBuf decompressed) {
byte[] in = new byte[decompressed.readableBytes()]; int len = decompressed.readableBytes();
decompressed.readBytes(in);
byte[] in;
int offset;
if (decompressed.hasArray()) {
in = decompressed.array();
offset = decompressed.arrayOffset() + decompressed.readerIndex();
} else {
in = new byte[len];
decompressed.getBytes(decompressed.readerIndex(), in);
offset = 0;
}
z.next_in = in; z.next_in = in;
z.next_in_index = 0; z.next_in_index = offset;
z.avail_in = in.length; z.avail_in = len;
} }
private void encode(ByteBuf compressed) { private ByteBuf encode(ByteBufAllocator alloc) {
boolean release = true;
ByteBuf out = null;
try { try {
byte[] out = new byte[(int) Math.ceil(z.next_in.length * 1.001) + 12]; int oldNextInIndex = z.next_in_index;
z.next_out = out; int oldNextOutIndex = z.next_out_index;
z.next_out_index = 0;
z.avail_out = out.length;
int resultCode = z.deflate(JZlib.Z_SYNC_FLUSH); int maxOutputLength = (int) Math.ceil(z.next_in.length * 1.001) + 12;
out = alloc.heapBuffer(maxOutputLength);
z.next_out = out.array();
z.next_out_index = out.arrayOffset() + out.writerIndex();
z.avail_out = maxOutputLength;
int resultCode;
try {
resultCode = z.deflate(JZlib.Z_SYNC_FLUSH);
} finally {
out.skipBytes(z.next_in_index - oldNextInIndex);
}
if (resultCode != JZlib.Z_OK) { if (resultCode != JZlib.Z_OK) {
throw new CompressionException("compression failure: " + resultCode); throw new CompressionException("compression failure: " + resultCode);
} }
if (z.next_out_index != 0) { int outputLength = z.next_out_index - oldNextOutIndex;
compressed.writeBytes(out, 0, z.next_out_index); if (outputLength > 0) {
out.writerIndex(out.writerIndex() + outputLength);
} }
release = false;
return out;
} finally { } finally {
// Deference the external references explicitly to tell the VM that // Deference the external references explicitly to tell the VM that
// the allocated byte arrays are temporary so that the call stack // the allocated byte arrays are temporary so that the call stack
@ -89,11 +114,14 @@ class SpdyHeaderBlockJZlibEncoder extends SpdyHeaderBlockRawEncoder {
// I'm not sure if the modern VMs do this optimization though. // I'm not sure if the modern VMs do this optimization though.
z.next_in = null; z.next_in = null;
z.next_out = null; z.next_out = null;
if (release && out != null) {
out.release();
}
} }
} }
@Override @Override
public ByteBuf encode(SpdyHeadersFrame frame) throws Exception { public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception {
if (frame == null) { if (frame == null) {
throw new IllegalArgumentException("frame"); throw new IllegalArgumentException("frame");
} }
@ -102,15 +130,17 @@ class SpdyHeaderBlockJZlibEncoder extends SpdyHeaderBlockRawEncoder {
return Unpooled.EMPTY_BUFFER; return Unpooled.EMPTY_BUFFER;
} }
ByteBuf decompressed = super.encode(frame); ByteBuf decompressed = super.encode(alloc, frame);
if (decompressed.readableBytes() == 0) { try {
return Unpooled.EMPTY_BUFFER; if (!decompressed.isReadable()) {
} return Unpooled.EMPTY_BUFFER;
}
ByteBuf compressed = decompressed.alloc().buffer(); setInput(decompressed);
setInput(decompressed); return encode(alloc);
encode(compressed); } finally {
return compressed; decompressed.release();
}
} }
@Override @Override

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import static io.netty.handler.codec.spdy.SpdyCodecUtil.*; import static io.netty.handler.codec.spdy.SpdyCodecUtil.*;
@ -61,7 +62,7 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
} }
@Override @Override
void decode(ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception {
if (headerBlock == null) { if (headerBlock == null) {
throw new NullPointerException("headerBlock"); throw new NullPointerException("headerBlock");
} }
@ -72,7 +73,7 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
if (cumulation == null) { if (cumulation == null) {
decodeHeaderBlock(headerBlock, frame); decodeHeaderBlock(headerBlock, frame);
if (headerBlock.isReadable()) { if (headerBlock.isReadable()) {
cumulation = headerBlock.alloc().buffer(headerBlock.readableBytes()); cumulation = alloc.buffer(headerBlock.readableBytes());
cumulation.writeBytes(headerBlock); cumulation.writeBytes(headerBlock);
} }
} else { } else {

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import java.util.Set; import java.util.Set;
@ -42,7 +43,7 @@ public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder {
} }
@Override @Override
public ByteBuf encode(SpdyHeadersFrame frame) throws Exception { public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception {
Set<String> names = frame.headers().names(); Set<String> names = frame.headers().names();
int numHeaders = names.size(); int numHeaders = names.size();
if (numHeaders == 0) { if (numHeaders == 0) {
@ -52,7 +53,7 @@ public class SpdyHeaderBlockRawEncoder extends SpdyHeaderBlockEncoder {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"header block contains too many headers"); "header block contains too many headers");
} }
ByteBuf headerBlock = Unpooled.buffer(); ByteBuf headerBlock = alloc.heapBuffer();
writeLengthField(headerBlock, numHeaders); writeLengthField(headerBlock, numHeaders);
for (String name: names) { for (String name: names) {
byte[] nameBytes = name.getBytes("UTF-8"); byte[] nameBytes = name.getBytes("UTF-8");

View File

@ -38,12 +38,12 @@ final class SpdyHeaderBlockZlibDecoder extends SpdyHeaderBlockRawDecoder {
} }
@Override @Override
void decode(ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception { void decode(ByteBufAllocator alloc, ByteBuf headerBlock, SpdyHeadersFrame frame) throws Exception {
int len = setInput(headerBlock); int len = setInput(headerBlock);
int numBytes; int numBytes;
do { do {
numBytes = decompress(headerBlock.alloc(), frame); numBytes = decompress(alloc, frame);
} while (numBytes > 0); } while (numBytes > 0);
// z_stream has an internal 64-bit hold buffer // z_stream has an internal 64-bit hold buffer

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import java.util.zip.Deflater; import java.util.zip.Deflater;
@ -52,10 +53,20 @@ class SpdyHeaderBlockZlibEncoder extends SpdyHeaderBlockRawEncoder {
return len; return len;
} }
private void encode(ByteBuf compressed) { private ByteBuf encode(ByteBufAllocator alloc, int len) {
while (compressInto(compressed)) { ByteBuf compressed = alloc.heapBuffer(len);
// Although unlikely, it's possible that the compressed size is larger than the decompressed size boolean release = true;
compressed.ensureWritable(compressed.capacity() << 1); try {
while (compressInto(compressed)) {
// Although unlikely, it's possible that the compressed size is larger than the decompressed size
compressed.ensureWritable(compressed.capacity() << 1);
}
release = false;
return compressed;
} finally {
if (release) {
compressed.release();
}
} }
} }
@ -69,7 +80,7 @@ class SpdyHeaderBlockZlibEncoder extends SpdyHeaderBlockRawEncoder {
} }
@Override @Override
public ByteBuf encode(SpdyHeadersFrame frame) throws Exception { public ByteBuf encode(ByteBufAllocator alloc, SpdyHeadersFrame frame) throws Exception {
if (frame == null) { if (frame == null) {
throw new IllegalArgumentException("frame"); throw new IllegalArgumentException("frame");
} }
@ -78,17 +89,17 @@ class SpdyHeaderBlockZlibEncoder extends SpdyHeaderBlockRawEncoder {
return Unpooled.EMPTY_BUFFER; return Unpooled.EMPTY_BUFFER;
} }
ByteBuf decompressed = super.encode(frame); ByteBuf decompressed = super.encode(alloc, frame);
if (decompressed.readableBytes() == 0) { try {
return Unpooled.EMPTY_BUFFER; if (!decompressed.isReadable()) {
return Unpooled.EMPTY_BUFFER;
}
int len = setInput(decompressed);
return encode(alloc, len);
} finally {
decompressed.release();
} }
ByteBuf compressed = decompressed.alloc().heapBuffer(decompressed.readableBytes());
int len = setInput(decompressed);
encode(compressed);
decompressed.skipBytes(len);
return compressed;
} }
@Override @Override

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import org.junit.After; import org.junit.After;
@ -52,7 +53,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testEmptyHeaderBlock() throws Exception { public void testEmptyHeaderBlock() throws Exception {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.EMPTY_BUFFER); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.EMPTY_BUFFER);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -64,7 +65,7 @@ public class SpdyHeaderBlockRawDecoderTest {
public void testZeroNameValuePairs() throws Exception { public void testZeroNameValuePairs() throws Exception {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(0); headerBlock.writeInt(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -76,7 +77,7 @@ public class SpdyHeaderBlockRawDecoderTest {
public void testNegativeNameValuePairs() throws Exception { public void testNegativeNameValuePairs() throws Exception {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(-1); headerBlock.writeInt(-1);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -91,7 +92,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -106,7 +107,7 @@ public class SpdyHeaderBlockRawDecoderTest {
public void testMissingNameLength() throws Exception { public void testMissingNameLength() throws Exception {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(1); headerBlock.writeInt(1);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -119,7 +120,7 @@ public class SpdyHeaderBlockRawDecoderTest {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(0); headerBlock.writeInt(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -131,7 +132,7 @@ public class SpdyHeaderBlockRawDecoderTest {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(-1); headerBlock.writeInt(-1);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -143,7 +144,7 @@ public class SpdyHeaderBlockRawDecoderTest {
ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8)); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -159,7 +160,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -172,7 +173,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -187,7 +188,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(0); headerBlock.writeInt(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -205,7 +206,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(-1); headerBlock.writeInt(-1);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -219,7 +220,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(5); headerBlock.writeInt(5);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -235,7 +236,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeByte(0); headerBlock.writeByte(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -251,7 +252,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(6); headerBlock.writeInt(6);
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -267,7 +268,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(6); headerBlock.writeInt(6);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
headerBlock.writeByte(0); headerBlock.writeByte(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -284,7 +285,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -307,7 +308,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
headerBlock.writeByte(0); headerBlock.writeByte(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -328,7 +329,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeByte(0); headerBlock.writeByte(0);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -344,7 +345,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -367,7 +368,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -386,7 +387,7 @@ public class SpdyHeaderBlockRawDecoderTest {
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
headerBlock.writeByte(0); headerBlock.writeByte(0);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
assertTrue(frame.isInvalid()); assertTrue(frame.isInvalid());
@ -408,7 +409,7 @@ public class SpdyHeaderBlockRawDecoderTest {
int readableBytes = headerBlock.readableBytes(); int readableBytes = headerBlock.readableBytes();
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(ByteBufAllocator.DEFAULT, headerBlockSegment, frame);
assertFalse(headerBlockSegment.isReadable()); assertFalse(headerBlockSegment.isReadable());
} }
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
@ -433,10 +434,10 @@ public class SpdyHeaderBlockRawDecoderTest {
valueBlock.writeInt(5); valueBlock.writeInt(5);
valueBlock.writeBytes(valueBytes); valueBlock.writeBytes(valueBytes);
decoder.decode(numHeaders, frame); decoder.decode(ByteBufAllocator.DEFAULT, numHeaders, frame);
decoder.decode(nameBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, nameBlock, frame);
frame.setInvalid(); frame.setInvalid();
decoder.decode(valueBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, valueBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(numHeaders.isReadable()); assertFalse(numHeaders.isReadable());
@ -458,7 +459,7 @@ public class SpdyHeaderBlockRawDecoderTest {
} }
headerBlock.writeInt(5); headerBlock.writeInt(5);
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -477,7 +478,7 @@ public class SpdyHeaderBlockRawDecoderTest {
for (int i = 0; i < maxHeaderSize - 3; i++) { for (int i = 0; i < maxHeaderSize - 3; i++) {
headerBlock.writeByte('a'); headerBlock.writeByte('a');
} }
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.spdy; package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import org.junit.After; import org.junit.After;
@ -68,7 +69,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
headerBlock.writeInt(5); // length of value headerBlock.writeInt(5); // length of value
headerBlock.writeBytes(valueBytes); headerBlock.writeBytes(valueBytes);
headerBlock.writeBytes(zlibSyncFlush); headerBlock.writeBytes(zlibSyncFlush);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -98,7 +99,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
int readableBytes = headerBlock.readableBytes(); int readableBytes = headerBlock.readableBytes();
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(ByteBufAllocator.DEFAULT, headerBlockSegment, frame);
assertFalse(headerBlockSegment.isReadable()); assertFalse(headerBlockSegment.isReadable());
} }
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
@ -126,7 +127,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
} }
headerBlock.writeInt(0); // length of value headerBlock.writeInt(0); // length of value
headerBlock.writeBytes(zlibSyncFlush); headerBlock.writeBytes(zlibSyncFlush);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -152,7 +153,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
headerBlock.writeByte('v'); headerBlock.writeByte('v');
} }
headerBlock.writeBytes(zlibSyncFlush); headerBlock.writeBytes(zlibSyncFlush);
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
assertFalse(headerBlock.isReadable()); assertFalse(headerBlock.isReadable());
@ -181,7 +182,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
headerBlock.writeByte(0x03); // adler-32 checksum headerBlock.writeByte(0x03); // adler-32 checksum
headerBlock.writeByte(0xc9); // adler-32 checksum headerBlock.writeByte(0xc9); // adler-32 checksum
headerBlock.writeByte(0); // Data following zlib stream headerBlock.writeByte(0); // Data following zlib stream
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
} }
@Test(expected = SpdyProtocolException.class) @Test(expected = SpdyProtocolException.class)
@ -194,7 +195,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
headerBlock.writeByte(0x03); // Unknown dictionary headerBlock.writeByte(0x03); // Unknown dictionary
headerBlock.writeByte(0x04); // Unknown dictionary headerBlock.writeByte(0x04); // Unknown dictionary
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
} }
@Test(expected = SpdyProtocolException.class) @Test(expected = SpdyProtocolException.class)
@ -206,6 +207,6 @@ public class SpdyHeaderBlockZlibDecoderTest {
headerBlock.writeByte(0x00); // little-endian length (0) headerBlock.writeByte(0x00); // little-endian length (0)
headerBlock.writeByte(0x00); // invalid one's compliment headerBlock.writeByte(0x00); // invalid one's compliment
headerBlock.writeByte(0x00); // invalid one's compliment headerBlock.writeByte(0x00); // invalid one's compliment
decoder.decode(headerBlock, frame); decoder.decode(ByteBufAllocator.DEFAULT, headerBlock, frame);
} }
} }