diff --git a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java index 4740d359e1..8bb07d1834 100644 --- a/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/compression/JdkZlibDecoder.java @@ -18,6 +18,7 @@ package io.netty.handler.codec.compression; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import java.nio.ByteOrder; import java.util.List; import java.util.zip.CRC32; import java.util.zip.DataFormatException; @@ -156,7 +157,7 @@ public class JdkZlibDecoder extends ZlibDecoder { if (outputLength > 0) { decompressed.writerIndex(decompressed.writerIndex() + outputLength); if (crc != null) { - crc.update(outArray, outIndex, length); + crc.update(outArray, outIndex, outputLength); } } else { if (inflater.needsDictionary()) { @@ -298,15 +299,10 @@ public class JdkZlibDecoder extends ZlibDecoder { gzipState = GzipState.PROCESS_FHCRC; case PROCESS_FHCRC: if ((flags & FHCRC) != 0) { - if (!in.isReadable()) { + if (in.readableBytes() < 4) { return false; } - int headerCrc = in.readShort(); - int readCrc = (int) crc.getValue() & 0xffff; - if (headerCrc != readCrc) { - throw new CompressionException( - "Header CRC value missmatch. Expected: " + headerCrc + ", Got: " + readCrc); - } + verifyCrc(in); } crc.reset(); gzipState = GzipState.HEADER_END; @@ -321,14 +317,14 @@ public class JdkZlibDecoder extends ZlibDecoder { if (buf.readableBytes() < 8) { return false; } - int dataCrc = buf.readInt(); - int readCrc = (int) crc.getValue() & 0xffff; - if (dataCrc != readCrc) { - throw new CompressionException( - "Data CRC value missmatch. Expected: " + dataCrc + ", Got: " + readCrc); - } - int dataLength = buf.readInt(); + verifyCrc(buf); + + // read ISIZE and verify + int dataLength = 0; + for (int i = 0; i < 4; ++i) { + dataLength |= buf.readUnsignedByte() << (i * 8); + } int readLength = inflater.getTotalOut(); if (dataLength != readLength) { throw new CompressionException( @@ -336,4 +332,16 @@ public class JdkZlibDecoder extends ZlibDecoder { } return true; } + + private void verifyCrc(ByteBuf in) { + long crcValue = 0; + for (int i = 0; i < 4; ++i) { + crcValue |= (long) in.readUnsignedByte() << (i * 8); + } + long readCrc = crc.getValue(); + if (crcValue != readCrc) { + throw new CompressionException( + "CRC value missmatch. Expected: " + crcValue + ", Got: " + readCrc); + } + } } diff --git a/codec/src/test/java/io/netty/handler/codec/compression/JZlibTest.java b/codec/src/test/java/io/netty/handler/codec/compression/JZlibTest.java index 44ebef4441..462862ea19 100644 --- a/codec/src/test/java/io/netty/handler/codec/compression/JZlibTest.java +++ b/codec/src/test/java/io/netty/handler/codec/compression/JZlibTest.java @@ -22,27 +22,31 @@ import io.netty.util.CharsetUtil; import org.junit.Test; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; -public class JZlibTest { +public class JZlibTest extends ZlibTest { + + @Override + protected ZlibEncoder createEncoder(ZlibWrapper wrapper) { + return new JZlibEncoder(wrapper); + } + + @Override + protected ZlibDecoder createDecoder(ZlibWrapper wrapper) { + return new JZlibDecoder(wrapper); + } @Test - public void testZLIB() throws Exception { + public void testZLIB_OR_NONE() throws Exception { ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); - EmbeddedChannel chEncoder = new EmbeddedChannel(new JZlibEncoder(ZlibWrapper.ZLIB)); + EmbeddedChannel chEncoder = new EmbeddedChannel(new JZlibEncoder(ZlibWrapper.NONE)); chEncoder.writeOutbound(data.copy()); assertTrue(chEncoder.finish()); ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - EmbeddedChannel chDecoderZlib = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB)); - - chDecoderZlib.writeInbound(deflatedData.copy()); - assertTrue(chDecoderZlib.finish()); - - assertEquals(data, chDecoderZlib.readInbound()); - EmbeddedChannel chDecoderZlibOrNone = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); chDecoderZlibOrNone.writeInbound(deflatedData); @@ -52,25 +56,17 @@ public class JZlibTest { } @Test - public void testNONE() throws Exception { + public void testZLIB_OR_NONE2() throws Exception { ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); - EmbeddedChannel chEncoder = new EmbeddedChannel(new JZlibEncoder(ZlibWrapper.NONE)); + EmbeddedChannel chEncoder = new EmbeddedChannel(new JZlibEncoder(ZlibWrapper.ZLIB)); chEncoder.writeOutbound(data.copy()); assertTrue(chEncoder.finish()); ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - EmbeddedChannel chDecoderZlibNone = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.NONE)); - - chDecoderZlibNone.writeInbound(deflatedData.copy()); - assertTrue(chDecoderZlibNone.finish()); - - assertEquals(data, chDecoderZlibNone.readInbound()); - - EmbeddedChannel chDecoderZlibOrNone = - new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); + EmbeddedChannel chDecoderZlibOrNone = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); chDecoderZlibOrNone.writeInbound(deflatedData); assertTrue(chDecoderZlibOrNone.finish()); @@ -79,7 +75,7 @@ public class JZlibTest { } @Test - public void testGZIP() throws Exception { + public void testZLIB_OR_NONE3() throws Exception { ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); EmbeddedChannel chEncoder = new EmbeddedChannel(new JZlibEncoder(ZlibWrapper.GZIP)); @@ -89,15 +85,7 @@ public class JZlibTest { ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - EmbeddedChannel chDecoderGZip = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.GZIP)); - - chDecoderGZip.writeInbound(deflatedData.copy()); - assertTrue(chDecoderGZip.finish()); - - assertEquals(data, chDecoderGZip.readInbound()); - - EmbeddedChannel chDecoderZlibOrNone = - new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); + EmbeddedChannel chDecoderZlibOrNone = new EmbeddedChannel(new JZlibDecoder(ZlibWrapper.ZLIB_OR_NONE)); chDecoderZlibOrNone.writeInbound(deflatedData); assertTrue(chDecoderZlibOrNone.finish()); diff --git a/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java b/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java index 40af2226c1..c8e494abe3 100644 --- a/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java +++ b/codec/src/test/java/io/netty/handler/codec/compression/JdkZlibTest.java @@ -15,76 +15,23 @@ */ package io.netty.handler.codec.compression; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.util.CharsetUtil; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -public class JdkZlibTest { +public class JdkZlibTest extends ZlibTest { - @Test - public void testZLIB() throws Exception { - ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); - - EmbeddedChannel chEncoder = new EmbeddedChannel(new JdkZlibEncoder(ZlibWrapper.ZLIB)); - - chEncoder.writeOutbound(data.copy()); - assertTrue(chEncoder.finish()); - - ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - - EmbeddedChannel chDecoderZlib = new EmbeddedChannel(new JdkZlibDecoder(ZlibWrapper.ZLIB)); - - chDecoderZlib.writeInbound(deflatedData.copy()); - assertTrue(chDecoderZlib.finish()); - - assertEquals(data, chDecoderZlib.readInbound()); + @Override + protected ZlibEncoder createEncoder(ZlibWrapper wrapper) { + return new JdkZlibEncoder(wrapper); } - @Test - public void testNONE() throws Exception { - ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); - - EmbeddedChannel chEncoder = new EmbeddedChannel(new JdkZlibEncoder(ZlibWrapper.NONE)); - - chEncoder.writeOutbound(data.copy()); - assertTrue(chEncoder.finish()); - - ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - - EmbeddedChannel chDecoderZlibNone = new EmbeddedChannel(new JdkZlibDecoder(ZlibWrapper.NONE)); - - chDecoderZlibNone.writeInbound(deflatedData.copy()); - assertTrue(chDecoderZlibNone.finish()); - - assertEquals(data, chDecoderZlibNone.readInbound()); + @Override + protected ZlibDecoder createDecoder(ZlibWrapper wrapper) { + return new JdkZlibDecoder(wrapper); } @Test(expected = IllegalArgumentException.class) public void testZLIB_OR_NONE() throws Exception { new JdkZlibDecoder(ZlibWrapper.ZLIB_OR_NONE); } - - @Test - public void testGZIP() throws Exception { - ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); - - EmbeddedChannel chEncoder = new EmbeddedChannel(new JdkZlibEncoder(ZlibWrapper.GZIP)); - - chEncoder.writeOutbound(data.copy()); - assertTrue(chEncoder.finish()); - - ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); - - EmbeddedChannel chDecoderGZip = new EmbeddedChannel(new JdkZlibDecoder(ZlibWrapper.GZIP)); - - chDecoderGZip.writeInbound(deflatedData.copy()); - assertTrue(chDecoderGZip.finish()); - - assertEquals(data, chDecoderGZip.readInbound()); - } } diff --git a/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java b/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java new file mode 100644 index 0000000000..898711f8e9 --- /dev/null +++ b/codec/src/test/java/io/netty/handler/codec/compression/ZlibTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2013 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.compression; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.util.CharsetUtil; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.GZIPOutputStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public abstract class ZlibTest { + + protected abstract ZlibEncoder createEncoder(ZlibWrapper wrapper); + protected abstract ZlibDecoder createDecoder(ZlibWrapper wrapper); + + @Test + public void testGZIP2() throws Exception { + ByteBuf data = Unpooled.wrappedBuffer("message".getBytes(CharsetUtil.UTF_8)); + ByteBuf deflatedData = Unpooled.wrappedBuffer(gzip("message")); + + EmbeddedChannel chDecoderGZip = new EmbeddedChannel(createDecoder(ZlibWrapper.GZIP)); + chDecoderGZip.writeInbound(deflatedData.copy()); + assertTrue(chDecoderGZip.finish()); + assertEquals(chDecoderGZip.readInbound(), data); + } + + @Test + public void testZLIB() throws Exception { + ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); + + EmbeddedChannel chEncoder = new EmbeddedChannel(createEncoder(ZlibWrapper.ZLIB)); + + chEncoder.writeOutbound(data.copy()); + assertTrue(chEncoder.finish()); + + ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); + + EmbeddedChannel chDecoderZlib = new EmbeddedChannel(createDecoder(ZlibWrapper.ZLIB)); + + chDecoderZlib.writeInbound(deflatedData.copy()); + assertTrue(chDecoderZlib.finish()); + + assertEquals(data, chDecoderZlib.readInbound()); + } + + @Test + public void testNONE() throws Exception { + ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); + + EmbeddedChannel chEncoder = new EmbeddedChannel(createEncoder(ZlibWrapper.NONE)); + + chEncoder.writeOutbound(data.copy()); + assertTrue(chEncoder.finish()); + + ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); + + EmbeddedChannel chDecoderZlibNone = new EmbeddedChannel(createDecoder(ZlibWrapper.NONE)); + + chDecoderZlibNone.writeInbound(deflatedData.copy()); + assertTrue(chDecoderZlibNone.finish()); + + assertEquals(data, chDecoderZlibNone.readInbound()); + } + + @Test + public void testGZIP() throws Exception { + ByteBuf data = Unpooled.copiedBuffer("test", CharsetUtil.UTF_8); + + EmbeddedChannel chEncoder = new EmbeddedChannel(createEncoder(ZlibWrapper.GZIP)); + + chEncoder.writeOutbound(data.copy()); + assertTrue(chEncoder.finish()); + + ByteBuf deflatedData = (ByteBuf) chEncoder.readOutbound(); + + EmbeddedChannel chDecoderGZip = new EmbeddedChannel(createDecoder(ZlibWrapper.GZIP)); + + chDecoderGZip.writeInbound(deflatedData.copy()); + assertTrue(chDecoderGZip.finish()); + + assertEquals(data, chDecoderGZip.readInbound()); + } + + private static byte[] gzip(String message) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + GZIPOutputStream stream = new GZIPOutputStream(out); + stream.write(message.getBytes(CharsetUtil.UTF_8)); + stream.close(); + return out.toByteArray(); + } + +}