示例#1
0
        public void CompressedFrame()
        {
            var encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            var decoderChannel = new EmbeddedChannel(new PerFrameDeflateDecoder(false));

            // initialize
            var payload = new byte[300];

            _random.NextBytes(payload);

            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(payload)));
            var compressedPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            var compressedFrame = new BinaryWebSocketFrame(true,
                                                           WebSocketRsv.Rsv1 | WebSocketRsv.Rsv3,
                                                           compressedPayload.Slice(0, compressedPayload.ReadableBytes - 4));

            // execute
            Assert.True(decoderChannel.WriteInbound(compressedFrame));
            var uncompressedFrame = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            // test
            Assert.NotNull(uncompressedFrame);
            Assert.NotNull(uncompressedFrame.Content);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame.Rsv);
            Assert.Equal(300, uncompressedFrame.Content.ReadableBytes);

            var finalPayload = new byte[300];

            uncompressedFrame.Content.ReadBytes(finalPayload);
            Assert.Equal(payload, finalPayload);
            uncompressedFrame.Release();
        }
示例#2
0
        static byte[] GzCompress(byte[] input)
        {
            ZlibEncoder encoder = ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.Gzip);
            var         channel = new EmbeddedChannel(encoder);

            Assert.True(channel.WriteOutbound(Unpooled.WrappedBuffer(input)));
            Assert.True(channel.Finish());  // close the channel to indicate end-of-data

            int         outputSize = 0;
            IByteBuffer o;
            var         outbound = new List <IByteBuffer>();

            while ((o = channel.ReadOutbound <IByteBuffer>()) != null)
            {
                outbound.Add(o);
                outputSize += o.ReadableBytes;
            }

            var output    = new byte[outputSize];
            int readCount = 0;

            foreach (IByteBuffer b in outbound)
            {
                int readableBytes = b.ReadableBytes;
                b.ReadBytes(output, readCount, readableBytes);
                b.Release();
                readCount += readableBytes;
            }
            Assert.True(channel.InboundMessages.Count == 0 && channel.OutboundMessages.Count == 0);

            return(output);
        }
示例#3
0
        public void DecompressionSkip()
        {
            EmbeddedChannel encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            EmbeddedChannel decoderChannel = new EmbeddedChannel(new PerFrameDeflateDecoder(false, AlwaysSkipWebSocketExtensionFilter.Instance));

            byte[] payload = new byte[300];
            _random.NextBytes(payload);

            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(payload)));
            var compressedPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            BinaryWebSocketFrame compressedBinaryFrame = new BinaryWebSocketFrame(
                true, WebSocketRsv.Rsv1 | WebSocketRsv.Rsv3, compressedPayload);

            Assert.True(decoderChannel.WriteInbound(compressedBinaryFrame));

            var inboundBinaryFrame = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            Assert.NotNull(inboundBinaryFrame);
            Assert.NotNull(inboundBinaryFrame.Content);
            Assert.Equal(compressedPayload, inboundBinaryFrame.Content);
            Assert.Equal(5, inboundBinaryFrame.Rsv);

            Assert.True(inboundBinaryFrame.Release());

            Assert.True(encoderChannel.FinishAndReleaseAll());
            Assert.False(decoderChannel.Finish());
        }
        /// <summary>
        /// Generate a new instance of an <see cref="EmbeddedChannel"/> capable of compressing data
        /// </summary>
        /// <param name="ctx">the context.</param>
        /// <param name="wrapper">Defines what type of encoder should be used</param>
        /// <returns></returns>
        private EmbeddedChannel NewCompressionChannel(IChannelHandlerContext ctx, ZlibWrapper wrapper)
        {
            var channel = ctx.Channel;

            return(new EmbeddedChannel(channel.Id, channel.Metadata.HasDisconnect,
                                       channel.Configuration, ZlibCodecFactory.NewZlibEncoder(wrapper, _compressionLevel, _windowBits,
                                                                                              _memLevel)));
        }
示例#5
0
        private IByteBuffer CompressContent(IChannelHandlerContext ctx, WebSocketFrame msg)
        {
            if (_encoder is null)
            {
                _encoder = new EmbeddedChannel(
                    ZlibCodecFactory.NewZlibEncoder(
                        ZlibWrapper.None,
                        _compressionLevel,
                        _windowSize,
                        8));
            }

            _ = _encoder.WriteOutbound(msg.Content.Retain());

            CompositeByteBuffer fullCompressedContent = ctx.Allocator.CompositeBuffer();

            while (true)
            {
                var partCompressedContent = _encoder.ReadOutbound <IByteBuffer>();
                if (partCompressedContent is null)
                {
                    break;
                }

                if (!partCompressedContent.IsReadable())
                {
                    _ = partCompressedContent.Release();
                    continue;
                }

                _ = fullCompressedContent.AddComponent(true, partCompressedContent);
            }

            if (fullCompressedContent.NumComponents <= 0)
            {
                _ = fullCompressedContent.Release();
                ThrowHelper.ThrowCodecException_CannotReadCompressedBuf();
            }

            if (msg.IsFinalFragment && _noContext)
            {
                Cleanup();
            }

            IByteBuffer compressedContent;

            if (RemoveFrameTail(msg))
            {
                int realLength = fullCompressedContent.ReadableBytes - FrameTail.ReadableBytes;
                compressedContent = fullCompressedContent.Slice(0, realLength);
            }
            else
            {
                compressedContent = fullCompressedContent;
            }
            return(compressedContent);
        }
        public void FragmentedFrame()
        {
            var encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            var decoderChannel = new EmbeddedChannel(new PerMessageDeflateDecoder(false));

            // initialize
            var payload = new byte[300];

            _random.NextBytes(payload);

            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(payload)));
            var compressedPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            compressedPayload = compressedPayload.Slice(0, compressedPayload.ReadableBytes - 4);

            int oneThird         = compressedPayload.ReadableBytes / 3;
            var compressedFrame1 = new BinaryWebSocketFrame(false,
                                                            WebSocketRsv.Rsv1 | WebSocketRsv.Rsv3,
                                                            compressedPayload.Slice(0, oneThird));
            var compressedFrame2 = new ContinuationWebSocketFrame(false,
                                                                  WebSocketRsv.Rsv3, compressedPayload.Slice(oneThird, oneThird));
            var compressedFrame3 = new ContinuationWebSocketFrame(true,
                                                                  WebSocketRsv.Rsv3, compressedPayload.Slice(oneThird * 2,
                                                                                                             compressedPayload.ReadableBytes - oneThird * 2));

            // execute
            Assert.True(decoderChannel.WriteInbound(compressedFrame1.Retain()));
            Assert.True(decoderChannel.WriteInbound(compressedFrame2.Retain()));
            Assert.True(decoderChannel.WriteInbound(compressedFrame3));
            var uncompressedFrame1 = decoderChannel.ReadInbound <BinaryWebSocketFrame>();
            var uncompressedFrame2 = decoderChannel.ReadInbound <ContinuationWebSocketFrame>();
            var uncompressedFrame3 = decoderChannel.ReadInbound <ContinuationWebSocketFrame>();

            // test
            Assert.NotNull(uncompressedFrame1);
            Assert.NotNull(uncompressedFrame2);
            Assert.NotNull(uncompressedFrame3);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame1.Rsv);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame2.Rsv);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame3.Rsv);

            IByteBuffer finalPayloadWrapped = Unpooled.WrappedBuffer(uncompressedFrame1.Content,
                                                                     uncompressedFrame2.Content, uncompressedFrame3.Content);

            Assert.Equal(300, finalPayloadWrapped.ReadableBytes);

            var finalPayload = new byte[300];

            finalPayloadWrapped.ReadBytes(finalPayload);
            Assert.Equal(payload, finalPayload);
            finalPayloadWrapped.Release();
        }
        public void IllegalStateWhenDecompressionInProgress()
        {
            var             selectivityDecompressionFilter = new SelectivityDecompressionFilter1();
            EmbeddedChannel encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            EmbeddedChannel decoderChannel = new EmbeddedChannel(
                new PerMessageDeflateDecoder(false, selectivityDecompressionFilter));

            byte[] firstPayload = new byte[200];
            _random.NextBytes(firstPayload);

            byte[] finalPayload = new byte[50];
            _random.NextBytes(finalPayload);

            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(firstPayload)));
            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(finalPayload)));
            var compressedFirstPayload = encoderChannel.ReadOutbound <IByteBuffer>();
            var compressedFinalPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            Assert.True(encoderChannel.FinishAndReleaseAll());

            BinaryWebSocketFrame       firstPart = new BinaryWebSocketFrame(false, WebSocketRsv.Rsv1, compressedFirstPayload);
            ContinuationWebSocketFrame finalPart = new ContinuationWebSocketFrame(true, WebSocketRsv.Rsv1, compressedFinalPayload);

            Assert.True(decoderChannel.WriteInbound(firstPart));

            var outboundFirstPart = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            //first part is decompressed
            Assert.Equal(0, outboundFirstPart.Rsv);
            Assert.Equal(firstPayload, ByteBufferUtil.GetBytes(outboundFirstPart.Content));
            Assert.True(outboundFirstPart.Release());

            //final part throwing exception
            try
            {
                decoderChannel.WriteInbound(finalPart);
                Assert.False(true);
            }
            catch (Exception exc)
            {
                Assert.IsType <DecoderException>(exc);
            }
            finally
            {
                Assert.True(finalPart.Release());
                Assert.False(encoderChannel.FinishAndReleaseAll());
            }
        }
示例#8
0
        protected override Result BeginEncode(IHttpResponse httpResponse, ICharSequence acceptEncoding)
        {
            if (this.contentSizeThreshold > 0)
            {
                if (httpResponse is IHttpContent httpContent &&
                    httpContent.Content.ReadableBytes < this.contentSizeThreshold)
                {
                    return(null);
                }
            }

            if (httpResponse.Headers.Contains(HttpHeaderNames.ContentEncoding))
            {
                // Content-Encoding was set, either as something specific or as the IDENTITY encoding
                // Therefore, we should NOT encode here
                return(null);
            }

            ZlibWrapper?wrapper = this.DetermineWrapper(acceptEncoding);

            if (wrapper is null)
            {
                return(null);
            }

            ICharSequence targetContentEncoding = null;

            switch (wrapper.Value)
            {
            case ZlibWrapper.Gzip:
                targetContentEncoding = GZipString;
                break;

            case ZlibWrapper.Zlib:
                targetContentEncoding = DeflateString;
                break;

            default:
                ThrowHelper.ThrowCodecException_InvalidCompression(wrapper.Value); break;
            }

            return(new Result(targetContentEncoding,
                              new EmbeddedChannel(
                                  this.handlerContext.Channel.Id,
                                  this.handlerContext.Channel.Metadata.HasDisconnect,
                                  this.handlerContext.Channel.Configuration,
                                  ZlibCodecFactory.NewZlibEncoder(
                                      wrapper.Value, this.compressionLevel, this.windowBits, this.memLevel))));
        }
示例#9
0
        protected override void InitChannel(ISocketChannel channel)
        {
            IChannelPipeline pipeline = channel.Pipeline;

            // Enable stream compression.
            pipeline.AddLast(ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.Gzip));
            pipeline.AddLast(ZlibCodecFactory.NewZlibDecoder(ZlibWrapper.Gzip));

            // Add the number codec first.
            pipeline.AddLast(new BigIntegerDecoder());
            pipeline.AddLast(new BigIntegerEncoder());

            // Add the business logic.
            pipeline.AddLast(new FactorialClientHandler());
        }
示例#10
0
        protected override void InitChannel(ISocketChannel channel)
        {
            IChannelPipeline pipeline = channel.Pipeline;

            // Enable stream compresion.
            pipeline.AddLast(ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.Gzip));
            pipeline.AddLast(ZlibCodecFactory.NewZlibDecoder(ZlibWrapper.Gzip));

            // Add the number codec first.
            pipeline.AddLast(new BigIntegerDecoder());
            pipeline.AddLast(new BigIntegerEncoder());

            // Add the business logic.
            // Please note, we create a handler for every new channel, because it has stateful properties.
            pipeline.AddLast(new FactorialServerHandler());
        }
示例#11
0
        public void MultiCompressedPayloadWithinFrame()
        {
            var encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            var decoderChannel = new EmbeddedChannel(new PerMessageDeflateDecoder(false));

            var payload1 = new byte[100];

            this.random.NextBytes(payload1);
            var payload2 = new byte[100];

            this.random.NextBytes(payload2);

            encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(payload1));
            var compressedPayload1 = encoderChannel.ReadOutbound <IByteBuffer>();

            encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(payload2));
            var compressedPayload2 = encoderChannel.ReadOutbound <IByteBuffer>();

            var compressedFrame = new BinaryWebSocketFrame(true,
                                                           WebSocketRsv.Rsv1 | WebSocketRsv.Rsv3,
                                                           Unpooled.WrappedBuffer(
                                                               compressedPayload1,
                                                               compressedPayload2.Slice(0, compressedPayload2.ReadableBytes - 4)));

            decoderChannel.WriteInbound(compressedFrame);
            var uncompressedFrame = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            Assert.NotNull(uncompressedFrame);
            Assert.NotNull(uncompressedFrame.Content);
            Assert.IsType <BinaryWebSocketFrame>(uncompressedFrame);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame.Rsv);
            Assert.Equal(200, uncompressedFrame.Content.ReadableBytes);

            var finalPayload1 = new byte[100];

            uncompressedFrame.Content.ReadBytes(finalPayload1);
            Assert.Equal(payload1, finalPayload1);
            var finalPayload2 = new byte[100];

            uncompressedFrame.Content.ReadBytes(finalPayload2);
            Assert.Equal(payload2, finalPayload2);
            uncompressedFrame.Release();
        }
示例#12
0
        public void CompressedEmptyFrame()
        {
            var encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            var decoderChannel = new EmbeddedChannel(new PerFrameDeflateDecoder(false));

            encoderChannel.WriteOutbound(Unpooled.Empty);
            var compressedPayload = encoderChannel.ReadOutbound <IByteBuffer>();
            var compressedFrame   =
                new BinaryWebSocketFrame(true, WebSocketRsv.Rsv1 | WebSocketRsv.Rsv3, compressedPayload);

            decoderChannel.WriteInbound(compressedFrame);
            var uncompressedFrame = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            Assert.NotNull(uncompressedFrame);
            Assert.NotNull(uncompressedFrame.Content);
            Assert.IsType <BinaryWebSocketFrame>(uncompressedFrame);
            Assert.Equal(WebSocketRsv.Rsv3, uncompressedFrame.Rsv);
            Assert.Equal(0, uncompressedFrame.Content.ReadableBytes);
            uncompressedFrame.Release();
        }
示例#13
0
        protected override Result BeginEncode(IHttpResponse headers, ICharSequence acceptEncoding)
        {
            if (headers.Headers.Contains(HttpHeaderNames.ContentEncoding))
            {
                // Content-Encoding was set, either as something specific or as the IDENTITY encoding
                // Therefore, we should NOT encode here
                return(null);
            }

            ZlibWrapper?wrapper = this.DetermineWrapper(acceptEncoding);

            if (wrapper == null)
            {
                return(null);
            }

            ICharSequence targetContentEncoding;

            switch (wrapper.Value)
            {
            case ZlibWrapper.Gzip:
                targetContentEncoding = GZipString;
                break;

            case ZlibWrapper.Zlib:
                targetContentEncoding = DeflateString;
                break;

            default:
                throw new CodecException($"{wrapper.Value} not supported, only Gzip and Zlib are allowed.");
            }

            return(new Result(targetContentEncoding,
                              new EmbeddedChannel(
                                  this.handlerContext.Channel.Id,
                                  this.handlerContext.Channel.Metadata.HasDisconnect,
                                  this.handlerContext.Channel.Configuration,
                                  ZlibCodecFactory.NewZlibEncoder(
                                      wrapper.Value, this.compressionLevel, this.windowBits, this.memLevel))));
        }
        public void SelectivityDecompressionSkip()
        {
            var             selectivityDecompressionFilter = new SelectivityDecompressionFilter0();
            EmbeddedChannel encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            EmbeddedChannel decoderChannel = new EmbeddedChannel(
                new PerMessageDeflateDecoder(false, selectivityDecompressionFilter));

            string textPayload = "compressed payload";

            byte[] binaryPayload = new byte[300];
            _random.NextBytes(binaryPayload);

            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(Encoding.UTF8.GetBytes(textPayload))));
            Assert.True(encoderChannel.WriteOutbound(Unpooled.WrappedBuffer(binaryPayload)));
            var compressedTextPayload   = encoderChannel.ReadOutbound <IByteBuffer>();
            var compressedBinaryPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            TextWebSocketFrame   compressedTextFrame   = new TextWebSocketFrame(true, WebSocketRsv.Rsv1, compressedTextPayload);
            BinaryWebSocketFrame compressedBinaryFrame = new BinaryWebSocketFrame(true, WebSocketRsv.Rsv1, compressedBinaryPayload);

            Assert.True(decoderChannel.WriteInbound(compressedTextFrame));
            Assert.True(decoderChannel.WriteInbound(compressedBinaryFrame));

            var inboundTextFrame   = decoderChannel.ReadInbound <TextWebSocketFrame>();
            var inboundBinaryFrame = decoderChannel.ReadInbound <BinaryWebSocketFrame>();

            Assert.Equal(WebSocketRsv.Rsv1, inboundTextFrame.Rsv);
            Assert.Equal(compressedTextPayload, inboundTextFrame.Content);
            Assert.True(inboundTextFrame.Release());

            Assert.Equal(0, inboundBinaryFrame.Rsv);
            Assert.Equal(binaryPayload, ByteBufferUtil.GetBytes(inboundBinaryFrame.Content));
            Assert.True(inboundBinaryFrame.Release());

            Assert.True(encoderChannel.FinishAndReleaseAll());
            Assert.False(decoderChannel.Finish());
        }
        public void FragmentedFrameWithLeftOverInLastFragment()
        {
            string hexDump = "677170647a777a737574656b707a787a6f6a7561756578756f6b7868616371716c657a6d64697479766d726f6" +
                             "269746c6376777464776f6f72767a726f64667278676764687775786f6762766d776d706b76697773777a7072" +
                             "6a6a737279707a7078697a6c69616d7461656d646278626d786f66666e686e776a7a7461746d7a776668776b6" +
                             "f6f736e73746575637a6d727a7175707a6e74627578687871767771697a71766c64626d78726d6d7675756877" +
                             "62667963626b687a726d676e646263776e67797264706d6c6863626577616967706a78636a72697464756e627" +
                             "977616f79736475676f76736f7178746a7a7479626c64636b6b6778637768746c62";
            EmbeddedChannel encoderChannel = new EmbeddedChannel(
                ZlibCodecFactory.NewZlibEncoder(ZlibWrapper.None, 9, 15, 8));
            EmbeddedChannel decoderChannel = new EmbeddedChannel(new PerMessageDeflateDecoder(false));

            IByteBuffer originPayload = Unpooled.WrappedBuffer(StringUtil.DecodeHexDump(hexDump));

            Assert.True(encoderChannel.WriteOutbound(originPayload.Duplicate().Retain()));

            var compressedPayload = encoderChannel.ReadOutbound <IByteBuffer>();

            compressedPayload = compressedPayload.Slice(0, compressedPayload.ReadableBytes - 4);

            int oneThird = compressedPayload.ReadableBytes / 3;

            TextWebSocketFrame compressedFrame1 = new TextWebSocketFrame(
                false, WebSocketRsv.Rsv1, compressedPayload.Slice(0, oneThird));
            ContinuationWebSocketFrame compressedFrame2 = new ContinuationWebSocketFrame(
                false, WebSocketRsv.Rsv3, compressedPayload.Slice(oneThird, oneThird));
            ContinuationWebSocketFrame compressedFrame3 = new ContinuationWebSocketFrame(
                false, WebSocketRsv.Rsv3, compressedPayload.Slice(oneThird * 2, oneThird));
            int offset = oneThird * 3;
            ContinuationWebSocketFrame compressedFrameWithExtraData = new ContinuationWebSocketFrame(
                true, WebSocketRsv.Rsv3, compressedPayload.Slice(offset,
                                                                 compressedPayload.ReadableBytes - offset));

            // check that last fragment contains only one extra byte
            Assert.Equal(1, compressedFrameWithExtraData.Content.ReadableBytes);
            Assert.Equal(1, compressedFrameWithExtraData.Content.GetByte(0));

            // write compressed frames
            Assert.True(decoderChannel.WriteInbound(compressedFrame1.Retain()));
            Assert.True(decoderChannel.WriteInbound(compressedFrame2.Retain()));
            Assert.True(decoderChannel.WriteInbound(compressedFrame3.Retain()));
            Assert.True(decoderChannel.WriteInbound(compressedFrameWithExtraData));

            // read uncompressed frames
            TextWebSocketFrame         uncompressedFrame1    = decoderChannel.ReadInbound <TextWebSocketFrame>();
            ContinuationWebSocketFrame uncompressedFrame2    = decoderChannel.ReadInbound <ContinuationWebSocketFrame>();
            ContinuationWebSocketFrame uncompressedFrame3    = decoderChannel.ReadInbound <ContinuationWebSocketFrame>();
            ContinuationWebSocketFrame uncompressedExtraData = decoderChannel.ReadInbound <ContinuationWebSocketFrame>();

            Assert.False(uncompressedExtraData.Content.IsReadable());

            var uncompressedPayload = Unpooled.WrappedBuffer(uncompressedFrame1.Content, uncompressedFrame2.Content,
                                                             uncompressedFrame3.Content, uncompressedExtraData.Content);

            Assert.Equal(originPayload, uncompressedPayload);

            Assert.True(originPayload.Release());
            Assert.True(uncompressedPayload.Release());

            Assert.True(encoderChannel.FinishAndReleaseAll());
            Assert.False(decoderChannel.Finish());
        }
示例#16
0
        protected internal override void Encode(IChannelHandlerContext ctx, WebSocketFrame msg, List <object> output)
        {
            if (this.encoder == null)
            {
                this.encoder = new EmbeddedChannel(
                    ZlibCodecFactory.NewZlibEncoder(
                        ZlibWrapper.None,
                        this.compressionLevel,
                        this.windowSize,
                        8));
            }

            this.encoder.WriteOutbound(msg.Content.Retain());

            CompositeByteBuffer fullCompressedContent = ctx.Allocator.CompositeBuffer();

            for (;;)
            {
                var partCompressedContent = this.encoder.ReadOutbound <IByteBuffer>();
                if (partCompressedContent == null)
                {
                    break;
                }

                if (!partCompressedContent.IsReadable())
                {
                    partCompressedContent.Release();
                    continue;
                }

                fullCompressedContent.AddComponent(true, partCompressedContent);
            }

            if (fullCompressedContent.NumComponents <= 0)
            {
                fullCompressedContent.Release();
                throw new CodecException("cannot read compressed buffer");
            }

            if (msg.IsFinalFragment && this.noContext)
            {
                this.Cleanup();
            }

            IByteBuffer compressedContent;

            if (this.RemoveFrameTail(msg))
            {
                int realLength = fullCompressedContent.ReadableBytes - FrameTail.Length;
                compressedContent = fullCompressedContent.Slice(0, realLength);
            }
            else
            {
                compressedContent = fullCompressedContent;
            }

            WebSocketFrame outMsg;

            if (msg is TextWebSocketFrame)
            {
                outMsg = new TextWebSocketFrame(msg.IsFinalFragment, this.Rsv(msg), compressedContent);
            }
            else if (msg is BinaryWebSocketFrame)
            {
                outMsg = new BinaryWebSocketFrame(msg.IsFinalFragment, this.Rsv(msg), compressedContent);
            }
            else if (msg is ContinuationWebSocketFrame)
            {
                outMsg = new ContinuationWebSocketFrame(msg.IsFinalFragment, this.Rsv(msg), compressedContent);
            }
            else
            {
                throw new CodecException($"unexpected frame type: {msg.GetType().Name}");
            }

            output.Add(outMsg);
        }