public void CustomHandshake()
        {
            var handshaker = new PerMessageDeflateServerExtensionHandshaker(6, true, 10, true, true);

            var parameters = new Dictionary <string, string>
            {
                { ClientMaxWindow, null },
                { ServerMaxWindow, "12" },
                { ClientNoContext, null },
                { ServerNoContext, null }
            };

            IWebSocketServerExtension extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, parameters));

            Assert.NotNull(extension);
            Assert.Equal(WebSocketRsv.Rsv1, extension.Rsv);
            Assert.IsType <PerMessageDeflateDecoder>(extension.NewExtensionDecoder());
            Assert.IsType <PerMessageDeflateEncoder>(extension.NewExtensionEncoder());

            WebSocketExtensionData data = extension.NewReponseData();

            Assert.Equal(PerMessageDeflateExtension, data.Name);
            Assert.Contains(ClientMaxWindow, data.Parameters.Keys);
            Assert.Equal("10", data.Parameters[ClientMaxWindow]);
            Assert.Contains(ServerMaxWindow, data.Parameters.Keys);
            Assert.Equal("12", data.Parameters[ServerMaxWindow]);

            parameters = new Dictionary <string, string>
            {
                { ServerMaxWindow, "12" },
                { ServerNoContext, null }
            };
            extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, parameters));

            Assert.NotNull(extension);
            Assert.Equal(WebSocketRsv.Rsv1, extension.Rsv);
            Assert.IsType <PerMessageDeflateDecoder>(extension.NewExtensionDecoder());
            Assert.IsType <PerMessageDeflateEncoder>(extension.NewExtensionEncoder());

            data = extension.NewReponseData();

            Assert.Equal(PerMessageDeflateExtension, data.Name);
            Assert.Equal(2, data.Parameters.Count);
            Assert.Contains(ServerMaxWindow, data.Parameters.Keys);
            Assert.Equal("12", data.Parameters[ServerMaxWindow]);
            Assert.Contains(ServerNoContext, data.Parameters.Keys);

            parameters = new Dictionary <string, string>();
            extension  = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, parameters));
            Assert.NotNull(extension);

            data = extension.NewReponseData();
            Assert.Equal(PerMessageDeflateExtension, data.Name);
            Assert.Empty(data.Parameters);
        }
        public void WebkitHandshake()
        {
            var handshaker = new DeflateFrameServerExtensionHandshaker();
            IWebSocketServerExtension extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(XWebkitDeflateFrameExtension, new Dictionary <string, string>()));

            Assert.NotNull(extension);
            Assert.Equal(WebSocketRsv.Rsv1, extension.Rsv);
            Assert.IsType <PerFrameDeflateDecoder>(extension.NewExtensionDecoder());
            Assert.IsType <PerFrameDeflateEncoder>(extension.NewExtensionEncoder());
        }
        public void FailedHandshake()
        {
            var handshaker = new DeflateFrameServerExtensionHandshaker();
            var parameters = new Dictionary <string, string>
            {
                { "unknown", "11" }
            };
            IWebSocketServerExtension extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(DeflateFrameExtension, parameters));

            Assert.Null(extension);
        }
        public void NormalHandshake()
        {
            var handshaker = new PerMessageDeflateServerExtensionHandshaker();
            IWebSocketServerExtension extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, new Dictionary <string, string>()));

            Assert.NotNull(extension);
            Assert.Equal(WebSocketRsv.Rsv1, extension.Rsv);
            Assert.IsType <PerMessageDeflateDecoder>(extension.NewExtensionDecoder());
            Assert.IsType <PerMessageDeflateEncoder>(extension.NewExtensionEncoder());

            WebSocketExtensionData data = extension.NewReponseData();

            Assert.Equal(PerMessageDeflateExtension, data.Name);
            Assert.Empty(data.Parameters);

            var parameters = new Dictionary <string, string>
            {
                { ClientMaxWindow, null },
                { ClientNoContext, null }
            };

            extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, parameters));

            Assert.NotNull(extension);
            Assert.Equal(WebSocketRsv.Rsv1, extension.Rsv);
            Assert.IsType <PerMessageDeflateDecoder>(extension.NewExtensionDecoder());
            Assert.IsType <PerMessageDeflateEncoder>(extension.NewExtensionEncoder());

            data = extension.NewReponseData();

            Assert.Equal(PerMessageDeflateExtension, data.Name);
            Assert.Empty(data.Parameters);

            parameters = new Dictionary <string, string>
            {
                { ServerMaxWindow, "12" },
                { ServerNoContext, null }
            };

            extension = handshaker.HandshakeExtension(
                new WebSocketExtensionData(PerMessageDeflateExtension, parameters));
            Assert.Null(extension);
        }
        public override void ChannelRead(IChannelHandlerContext ctx, object msg)
        {
            if (msg is IHttpRequest request)
            {
                if (WebSocketExtensionUtil.IsWebsocketUpgrade(request.Headers))
                {
                    if (request.Headers.TryGet(HttpHeaderNames.SecWebsocketExtensions, out ICharSequence value) &&
                        value is object)
                    {
                        string extensionsHeader = value.ToString();
                        List <WebSocketExtensionData> extensions =
                            WebSocketExtensionUtil.ExtractExtensions(extensionsHeader);
                        int rsv = 0;

                        for (int i = 0; i < extensions.Count; i++)
                        {
                            WebSocketExtensionData    extensionData  = extensions[i];
                            IWebSocketServerExtension validExtension = null;
                            for (int j = 0; j < _extensionHandshakers.Count; j++)
                            {
                                validExtension = _extensionHandshakers[j].HandshakeExtension(extensionData);
                                if (validExtension is object)
                                {
                                    break;
                                }
                            }

                            if (validExtension is object && 0u >= (uint)(validExtension.Rsv & rsv))
                            {
                                if (_validExtensions is null)
                                {
                                    _validExtensions = CreateValidExtensions();
                                }

                                rsv |= validExtension.Rsv;
                                _validExtensions.Add(validExtension);
                            }
                        }
                    }
                }
            }

            base.ChannelRead(ctx, msg);
        }
        public override void ChannelRead(IChannelHandlerContext ctx, object msg)
        {
            if (msg is IHttpRequest request)
            {
                if (WebSocketExtensionUtil.IsWebsocketUpgrade(request.Headers))
                {
                    if (request.Headers.TryGet(HttpHeaderNames.SecWebsocketExtensions, out ICharSequence value) &&
                        value != null)
                    {
                        string extensionsHeader = value.ToString();
                        List <WebSocketExtensionData> extensions =
                            WebSocketExtensionUtil.ExtractExtensions(extensionsHeader);
                        int rsv = 0;

                        foreach (WebSocketExtensionData extensionData in extensions)
                        {
                            IWebSocketServerExtension validExtension = null;
                            foreach (IWebSocketServerExtensionHandshaker extensionHandshaker in this.extensionHandshakers)
                            {
                                validExtension = extensionHandshaker.HandshakeExtension(extensionData);
                                if (validExtension != null)
                                {
                                    break;
                                }
                            }

                            if (validExtension != null && (validExtension.Rsv & rsv) == 0)
                            {
                                if (this.validExtensions == null)
                                {
                                    this.validExtensions = new List <IWebSocketServerExtension>(1);
                                }

                                rsv = rsv | validExtension.Rsv;
                                this.validExtensions.Add(validExtension);
                            }
                        }
                    }
                }
            }

            base.ChannelRead(ctx, msg);
        }
        private static void SwitchWebSocketExtensionHandler(Task promise, object state)
        {
            var wrapped         = (Tuple <IChannelHandlerContext, List <IWebSocketServerExtension> >)state;
            var ctx             = wrapped.Item1;
            var validExtensions = wrapped.Item2;
            var pipeline        = ctx.Pipeline;

            if (promise.IsSuccess())
            {
                for (int i = 0; i < validExtensions.Count; i++)
                {
                    IWebSocketServerExtension extension = validExtensions[i];
                    WebSocketExtensionDecoder decoder   = extension.NewExtensionDecoder();
                    WebSocketExtensionEncoder encoder   = extension.NewExtensionEncoder();
                    _ = pipeline
                        .AddAfter(ctx.Name, decoder.GetType().Name, decoder)
                        .AddAfter(ctx.Name, encoder.GetType().Name, encoder);
                }
            }
        }