Exemple #1
0
        public void UnderstandEncodedCookies()
        {
            var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions {
                Logger = this.logger
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=This%20is%20encoded.");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.True((bool)result.IsValidWebSocketRequest);
                        Assert.Equal(1, result.Request.Cookies.Count);
                        Assert.Equal((string)"This is encoded.", (string)result.Request.Cookies["key"].Value);
                    }
        }
        public void WebSocketHandshaker_CanParseMultipleCookie()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories,
                                                                     new WebSocketListenerOptions()
            {
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: cookie1=uno; cookie2=dos");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.NotNull(result);

                Assert.AreEqual(2, result.Request.Cookies.Count);
            }
        }
        private async Task NegotiateWebSocket(Socket client)
        {
            WebSocketNegotiationResult result;

            try
            {
                var timeoutTask = Task.Delay(_options.NegotiationTimeout);
#if (NET45 || NET451 || NET452 || NET46)
                Stream stream = new NetworkStream(client, FileAccess.ReadWrite, true);
#elif (DNX451 || DNX452 || DNX46 || NETSTANDARD || UAP10_0 || DOTNET5_4 || NETSTANDARDAPP1_5)
                Stream stream = new NetworkStream(client);
#endif
                foreach (var conExt in _extensions)
                {
                    var extTask = conExt.ExtendConnectionAsync(stream);
                    await Task.WhenAny(timeoutTask, extTask).ConfigureAwait(false);

                    if (timeoutTask.IsCompleted)
                    {
                        throw new WebSocketException("Negotiation timeout (Extension: " + conExt.GetType().Name + ")");
                    }

                    stream = await extTask;
                }

                var handshakeTask = _handShaker.HandshakeAsync(stream);
                await Task.WhenAny(timeoutTask, handshakeTask).ConfigureAwait(false);

                if (timeoutTask.IsCompleted)
                {
                    throw new WebSocketException("Negotiation timeout");
                }

                var handshake = await handshakeTask;

                if (handshake.IsValid)
                {
                    result = new WebSocketNegotiationResult(handshake.Factory.CreateWebSocket(stream, _options, (IPEndPoint)client.LocalEndPoint, (IPEndPoint)client.RemoteEndPoint, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions));
                }
                else
                {
                    SafeEnd.Dispose(client);
                    result = new WebSocketNegotiationResult(handshake.Error);
                }
            }
            catch (Exception ex)
            {
                SafeEnd.Dispose(client);
                result = new WebSocketNegotiationResult(ExceptionDispatchInfo.Capture(ex));
            }

            try
            {
                await _negotiations.SendAsync(result, _cancel.Token).ConfigureAwait(false);
            }
            finally
            {
                _semaphore.Release();
            }
        }
Exemple #4
0
        public void DoSimpleHandshakeWithEndpoints()
        {
            var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions {
                Logger = this.logger
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;

                        Assert.Equal(connection.LocalEndPoint.ToString(), result.Request.LocalEndPoint.ToString());
                        Assert.Equal(connection.RemoteEndPoint.ToString(), result.Request.RemoteEndPoint.ToString());
                    }
        }
Exemple #5
0
        public void ParseMultipleCookie()
        {
            var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions {
                Logger = this.logger
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: cookie1=uno; cookie2=dos");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);

                        Assert.Equal(2, result.Request.Cookies.Count);
                    }
        }
Exemple #6
0
        public void IndicateANonWebSocketConnection()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            var ext = new WebSocketExtension("test-extension", new List <WebSocketExtensionOption>(new[]
            {
                new WebSocketExtensionOption("optionA")
            }));
            IWebSocketMessageExtensionContext ctx;

            extension.Setup(x => x.TryNegotiate(It.IsAny <WebSocketHttpRequest>(), out ext, out ctx))
            .Returns(true);

            var factory = new WebSocketFactoryRfc6455();

            factory.MessageExtensions.Add(extension.Object);
            var factories = new WebSocketFactoryCollection();

            factories.Add(factory);
            var handshaker = new WebSocketHandshaker(factories, new WebSocketListenerOptions
            {
                Logger       = this.logger,
                SubProtocols = new[]
                {
                    "superchat"
                }
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.False((bool)result.IsWebSocketRequest);
                        Assert.False((bool)result.IsVersionSupported);

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 400 Bad Request");
                        sb.AppendLine(@"Connection: close");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
Exemple #7
0
        public void WebSocketHandshaker_CanUnderstandEncodedCookies()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories,
                                                                     new WebSocketListenerOptions()
            {
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=This%20is%20encoded.");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsValid);
                Assert.AreEqual(1, result.Request.Cookies.Count);
                Assert.AreEqual("This is encoded.", result.Request.Cookies[0].Value);
            }
        }
        public void WebSocketHandshaker_FailsWhenBadExtensionRequest()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            WebSocketExtension ext = new WebSocketExtension("test-extension", new List <WebSocketExtensionOption>(new[] { new WebSocketExtensionOption()
                                                                                                                          {
                                                                                                                              ClientAvailableOption = false, Name = "optionA"
                                                                                                                          } }));
            IWebSocketMessageExtensionContext ctx;

            extension.Setup(x => x.TryNegotiate(It.IsAny <WebSocketHttpRequest>(), out ext, out ctx))
            .Returns(true);

            var config = new WebSocketListenerConfig(new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchat" }
            });

            config.Standards.RegisterStandard(new WebSocketFactoryRfc6455());
            config.MessageExtensions.RegisterExtension(extension.Object);
            var handshaker = new WebSocketHandshaker(config);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                    sw.WriteLine(@"Sec-WebSocket-Extensions: test-extension;;Dsf,,optionA");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.IsTrue(result.IsVersionSupported);
                Assert.IsTrue(result.NegotiatedMessageExtensions.Count() == 0);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 400 Bad Request");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #9
0
        WebSocketHandshake GenerateSimpleHandshake()
        {
            var config = new WebSocketListenerConfig(new WebSocketListenerOptions());

            config.Standards.RegisterStandard(new WebSocketFactoryRfc6455());
            WebSocketHandshaker handshaker = new WebSocketHandshaker(config);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                ms.Seek(0, SeekOrigin.Begin);

                return(handshaker.HandshakeAsync(ms).Result);
            }
        }
        public void WebSocketHandshaker_CanDoSimpleHandshake_with_Endpoints()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, new WebSocketListenerOptions());

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms, new IPEndPoint(IPAddress.Parse("10.0.0.1"), 8888), new IPEndPoint(IPAddress.Parse("192.168.0.2"), 9999)).Result;
                Assert.AreEqual("10.0.0.1", result.Request.LocalEndpoint.Address.ToString());
                Assert.AreEqual(8888, result.Request.LocalEndpoint.Port);
                Assert.AreEqual("192.168.0.2", result.Request.RemoteEndpoint.Address.ToString());
                Assert.AreEqual(9999, result.Request.RemoteEndpoint.Port);
            }
        }
Exemple #11
0
        public void SimpleHandshakeIgnoringFallback()
        {
            var options = new WebSocketListenerOptions {
                Logger = this.logger
            };

            options.HttpFallback = this.fallback.Object;
            var handshaker = new WebSocketHandshaker(this.factories, options);

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.True((bool)result.IsWebSocketRequest);
                        Assert.True((bool)result.IsVersionSupported);
                        Assert.Equal(new Uri("http://example.com"), new Uri(result.Request.Headers[RequestHeader.Origin]));
                        Assert.Equal((string)"server.example.com", (string)result.Request.Headers[RequestHeader.Host]);
                        Assert.Equal((string)@"/chat", (string)result.Request.RequestUri.ToString());
                        Assert.Equal(1, result.Request.Cookies.Count);
                        var cookie = result.Request.Cookies["key"];
                        Assert.Equal((string)"key", (string)cookie.Name);
                        Assert.Equal((string)@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", (string)cookie.Value);
                        Assert.NotNull(result.Request.LocalEndPoint);
                        Assert.NotNull(result.Request.RemoteEndPoint);

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                        sb.AppendLine(@"Upgrade: websocket");
                        sb.AppendLine(@"Connection: Upgrade");
                        sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
Exemple #12
0
        public void WebSocketHandshaker_CanDoSimpleHandshakeIgnoringFallback()
        {
            var options = new WebSocketListenerOptions();

            options.HttpFallback = _fallback.Object;
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, options);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.IsTrue(result.IsVersionSupported);
                Assert.AreEqual(new Uri("http://example.com"), result.Request.Headers.Origin);
                Assert.AreEqual("server.example.com", result.Request.Headers[HttpRequestHeader.Host]);
                Assert.AreEqual(@"/chat", result.Request.RequestUri.ToString());
                Assert.AreEqual(1, result.Request.Cookies.Count);
                var cookie = result.Request.Cookies["key"];
                Assert.AreEqual("key", cookie.Name);
                Assert.AreEqual(@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", cookie.Value);
                Assert.IsNotNull(result.Request.LocalEndpoint);
                Assert.IsNotNull(result.Request.RemoteEndpoint);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                sb.AppendLine(@"Upgrade: websocket");
                sb.AppendLine(@"Connection: Upgrade");
                sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #13
0
        public void DoesNotFailWhenSubProtocolRequestedButNoMatch()
        {
            var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions
            {
                Logger       = this.logger,
                SubProtocols = new[]
                {
                    "superchat2", "text"
                }
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.True((bool)result.IsWebSocketRequest);
                        Assert.True((bool)result.IsVersionSupported);
                        Assert.Null(result.Error);
                        Assert.True((bool)result.IsValidWebSocketRequest);
                        Assert.True(string.IsNullOrEmpty(result.Response.Headers[ResponseHeader.WebSocketProtocol]));

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                        sb.AppendLine(@"Upgrade: websocket");
                        sb.AppendLine(@"Connection: Upgrade");
                        sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
        public void WebSocketHandshaker_CanReturnCookies()
        {
            var config = new WebSocketListenerConfig(new WebSocketListenerOptions()
            {
                OnHttpNegotiation = async(request, response) =>
                {
                    response.Cookies.Add(new System.Net.Cookie("name1", "value1"));
                    response.Cookies.Add(new System.Net.Cookie("name2", "value2"));
                }
            });

            config.Standards.RegisterStandard(new WebSocketFactoryRfc6455());

            var handshaker = new WebSocketHandshaker(config);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                sb.AppendLine(@"Upgrade: websocket");
                sb.AppendLine(@"Connection: Upgrade");
                sb.AppendLine(@"Set-Cookie: name1=value1");
                sb.AppendLine(@"Set-Cookie: name2=value2");
                sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #15
0
        public void ReturnCookies()
        {
            var handshaker = new WebSocketHandshaker(this.factories,
                                                     new WebSocketListenerOptions
            {
                Logger = this.logger,
                HttpAuthenticationHandler = async(request, response) =>
                {
                    response.Cookies.Add(new Cookie("name1", "value1"));
                    response.Cookies.Add(new Cookie("name2", "value2"));
                    return(true);
                }
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                        sb.AppendLine(@"Upgrade: websocket");
                        sb.AppendLine(@"Connection: Upgrade");
                        sb.AppendLine(@"Set-Cookie: name1=value1");
                        sb.AppendLine(@"Set-Cookie: name2=value2");
                        sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
Exemple #16
0
        public void WebSocketHandshaker_CanIndicateANonWebSocketConnection()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            WebSocketExtension ext = new WebSocketExtension("test-extension", new List <WebSocketExtensionOption>(new[] { new WebSocketExtensionOption()
                                                                                                                          {
                                                                                                                              ClientAvailableOption = false, Name = "optionA"
                                                                                                                          } }));
            IWebSocketMessageExtensionContext ctx;

            extension.Setup(x => x.TryNegotiate(It.IsAny <WebSocketHttpRequest>(), out ext, out ctx))
            .Returns(true);

            var factory = new WebSocketFactoryRfc6455();

            factory.MessageExtensions.RegisterExtension(extension.Object);
            var factories = new WebSocketFactoryCollection();

            factories.RegisterStandard(factory);
            WebSocketHandshaker handshaker = new WebSocketHandshaker(factories, new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchat" }
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsFalse(result.IsWebSocketRequest);
                Assert.IsFalse(result.IsVersionSupported);
                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 400 Bad Request");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
        public void WebSocketHandshaker_DoesNotFailWhenSubProtocolRequestedButNoMatch()
        {
            var config = new WebSocketListenerConfig(new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchatx" }
            });

            config.Standards.RegisterStandard(new WebSocketFactoryRfc6455());
            var handshaker = new WebSocketHandshaker(config);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.IsTrue(result.IsVersionSupported);
                Assert.IsNull(result.Error);
                Assert.IsTrue(result.IsValid);
                Assert.IsNull(result.Response.WebSocketProtocol);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                sb.AppendLine(@"Upgrade: websocket");
                sb.AppendLine(@"Connection: Upgrade");
                sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #18
0
        public void SendCustomErrorCode()
        {
            var handshaker = new WebSocketHandshaker(this.factories,
                                                     new WebSocketListenerOptions
            {
                Logger = this.logger,
                HttpAuthenticationHandler = async(req, res) =>
                {
                    res.Status = HttpStatusCode.Unauthorized;
                    return(false);
                }
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.False((bool)result.IsValidWebSocketRequest);
                        Assert.NotNull(result.Error);

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 401 Unauthorized");
                        sb.AppendLine(@"Connection: close");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
Exemple #19
0
        private async Task <WebSocketHandshake> HandshakeAsync(Stream stream, Task timeoutTask)
        {
            var handshakeTask = _handShaker.HandshakeAsync(stream);
            await Task.WhenAny(timeoutTask, handshakeTask).ConfigureAwait(false);

            if (timeoutTask.IsCompleted)
            {
                throw new WebSocketException("Negotiation timeout");
            }

            var handshake = await handshakeTask;

            return(handshake);
        }
Exemple #20
0
        public void WebSocketHandshaker_CanNegotiateAndIgnoreAnExtension()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchat" }
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                    sw.WriteLine(@"Sec-WebSocket-Extensions: test-extension");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.AreEqual(new Uri("http://example.com"), result.Request.Headers.Origin);
                Assert.AreEqual("superchat", result.Response.WebSocketProtocol);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                sb.AppendLine(@"Upgrade: websocket");
                sb.AppendLine(@"Connection: Upgrade");
                sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                sb.AppendLine(@"Sec-WebSocket-Protocol: superchat");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
        public void WebSocketHandshaker_CanDetectReturnCookieErrors()
        {
            var config = new WebSocketListenerConfig(new WebSocketListenerOptions()
            {
                OnHttpNegotiation = (req, res) => { throw new Exception("dummy"); }
            });

            config.Standards.RegisterStandard(new WebSocketFactoryRfc6455());
            var handshaker = new WebSocketHandshaker(config);


            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsFalse(result.IsValid);
                Assert.IsNotNull(result.Error);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 500 Internal Server Error");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #22
0
        public void WebSocketHandshaker_FailWhenSubProtocolRequestedButNoMatch()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchat2", "text" }
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.IsTrue(result.IsVersionSupported);
                Assert.IsNotNull(result.Error);
                Assert.IsFalse(result.IsValid);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 400 Bad Request");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #23
0
        public void WebSocketHandshaker_CanSendCustomErrorCode()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories,
                                                                     new WebSocketListenerOptions()
            {
                OnHttpNegotiation = (req, res) => { res.Status = HttpStatusCode.Unauthorized; }
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsFalse(result.IsValid);
                Assert.IsNull(result.Error);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 401 Unauthorized");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
Exemple #24
0
        public void HttpFallback()
        {
            var options = new WebSocketListenerOptions {
                Logger = this.logger
            };

            options.HttpFallback = this.fallback.Object;
            var handshaker = new WebSocketHandshaker(this.factories, options);

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.False((bool)result.IsWebSocketRequest);
                        Assert.False((bool)result.IsValidWebSocketRequest);
                        Assert.True((bool)result.IsValidHttpRequest);
                        Assert.False((bool)result.IsVersionSupported);
                        Assert.Equal(new Uri("http://example.com"), new Uri(result.Request.Headers[RequestHeader.Origin]));
                        Assert.Equal((string)"server.example.com", (string)result.Request.Headers[RequestHeader.Host]);
                        Assert.Equal((string)@"/chat", (string)result.Request.RequestUri.ToString());
                        Assert.Equal(1, result.Request.Cookies.Count);
                        var cookie = result.Request.Cookies["key"];
                        Assert.Equal((string)"key", (string)cookie.Name);
                        Assert.Equal((string)@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", (string)cookie.Value);
                        Assert.NotNull(result.Request.LocalEndPoint);
                        Assert.NotNull(result.Request.RemoteEndPoint);
                    }
        }
Exemple #25
0
        public void WebSocketHandshaker_CanDoHttpFallback()
        {
            var options = new WebSocketListenerOptions();

            options.HttpFallback = _fallback.Object;
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories, options);

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsFalse(result.IsWebSocketRequest);
                Assert.IsFalse(result.IsValidWebSocketRequest);
                Assert.IsTrue(result.IsValidHttpRequest);
                Assert.IsFalse(result.IsVersionSupported);
                Assert.AreEqual(new Uri("http://example.com"), result.Request.Headers.Origin);
                Assert.AreEqual("server.example.com", result.Request.Headers[HttpRequestHeader.Host]);
                Assert.AreEqual(@"/chat", result.Request.RequestUri.ToString());
                Assert.AreEqual(1, result.Request.Cookies.Count);
                var cookie = result.Request.Cookies["key"];
                Assert.AreEqual("key", cookie.Name);
                Assert.AreEqual(@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", cookie.Value);
                Assert.IsNotNull(result.Request.LocalEndpoint);
                Assert.IsNotNull(result.Request.RemoteEndpoint);
            }
        }
Exemple #26
0
        private WebSocketHandshake GenerateSimpleHandshake()
        {
            var handshaker = new WebSocketHandshaker(this.factories, this.options);

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        return(handshaker.HandshakeAsync(connection).Result);
                    }
        }
Exemple #27
0
        private async Task NegotiateWebSocket(NetworkConnection networkConnection)
        {
            if (networkConnection == null)
            {
                throw new ArgumentNullException(nameof(networkConnection));
            }

            await Task.Yield();

            WebSocketNegotiationResult result;

            try
            {
                var timeoutTask = Task.Delay(_options.NegotiationTimeout);

                foreach (var conExt in _extensions)
                {
                    var extTask = conExt.ExtendConnectionAsync(networkConnection);
                    await Task.WhenAny(timeoutTask, extTask).ConfigureAwait(false);

                    if (timeoutTask.IsCompleted)
                    {
#pragma warning disable 4014
                        extTask.IgnoreFaultOrCancellation(); // make connection exception observed
#pragma warning restore 4014
                        throw new WebSocketException($"Negotiation timeout (Extension: {conExt.GetType().Name})");
                    }

                    networkConnection = await extTask.ConfigureAwait(false);
                }

                var handshakeTask = _handShaker.HandshakeAsync(networkConnection);
                await Task.WhenAny(timeoutTask, handshakeTask).ConfigureAwait(false);

                if (timeoutTask.IsCompleted)
                {
#pragma warning disable 4014
                    handshakeTask.IgnoreFaultOrCancellation(); // make connection exception observed
#pragma warning restore 4014
                    throw new WebSocketException("Negotiation timeout");
                }

                var handshake = await handshakeTask.ConfigureAwait(false);

                if (handshake.IsValidWebSocketRequest)
                {
                    result = new WebSocketNegotiationResult(handshake.Factory.CreateWebSocket(networkConnection, _options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions));
                }
                else if (handshake.IsValidHttpRequest && _options.HttpFallback != null)
                {
                    _options.HttpFallback.Post(handshake.Request, networkConnection);
                    return;
                }
                else
                {
                    SafeEnd.Dispose(networkConnection, this.log);
                    result = new WebSocketNegotiationResult(handshake.Error);
                }

                var webSocket = result.Result;
                if (_negotiations.TryEnqueue(result) == false)
                {
                    SafeEnd.Dispose(webSocket);
                    return; // too many negotiations
                }

                if (webSocket != null)
                {
                    this.pingQueue?.GetSubscriptionList().Add(webSocket);
                }
            }
            catch (Exception negotiationError)
            {
                if (this.log.IsDebugEnabled)
                {
                    this.log.Debug("An error occurred while negotiating WebSocket request.", negotiationError);
                }

                SafeEnd.Dispose(networkConnection, this.log);
                result = new WebSocketNegotiationResult(ExceptionDispatchInfo.Capture(negotiationError));
            }
            finally
            {
                _semaphore.Release();
            }
        }
Exemple #28
0
        public void NegotiateAnExtensionWithParameters()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            var ext = new WebSocketExtension("test-extension", new List <WebSocketExtensionOption>(new[]
            {
                new WebSocketExtensionOption("optionA")
            }));
            IWebSocketMessageExtensionContext ctx;

            extension.Setup(x => x.TryNegotiate(It.IsAny <WebSocketHttpRequest>(), out ext, out ctx))
            .Returns(true);

            var factory = new WebSocketFactoryRfc6455();

            factory.MessageExtensions.Add(extension.Object);
            var factories = new WebSocketFactoryCollection();

            factories.Add(factory);
            var handshaker = new WebSocketHandshaker(factories, new WebSocketListenerOptions
            {
                Logger       = this.logger,
                SubProtocols = new[]
                {
                    "superchat"
                }
            });

            using (var connectionInput = new MemoryStream())
                using (var connectionOutput = new MemoryStream())
                    using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput))
                    {
                        using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true))
                        {
                            sw.WriteLine(@"GET /chat HTTP/1.1");
                            sw.WriteLine(@"Host: server.example.com");
                            sw.WriteLine(@"Upgrade: websocket");
                            sw.WriteLine(@"Connection: Upgrade");
                            sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                            sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                            sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                            sw.WriteLine(@"Sec-WebSocket-Extensions: test-extension;optionA");
                            sw.WriteLine(@"Sec-WebSocket-Version: 13");
                            sw.WriteLine(@"Origin: http://example.com");
                        }

                        connectionInput.Seek(0, SeekOrigin.Begin);

                        var result = handshaker.HandshakeAsync(connection).Result;
                        Assert.NotNull(result);
                        Assert.True((bool)result.IsWebSocketRequest);
                        Assert.Equal(new Uri("http://example.com"), new Uri(result.Request.Headers[RequestHeader.Origin]));
                        Assert.Equal((string)"superchat", (string)result.Response.Headers[ResponseHeader.WebSocketProtocol]);

                        connectionOutput.Seek(0, SeekOrigin.Begin);

                        var sb = new StringBuilder();
                        sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                        sb.AppendLine(@"Upgrade: websocket");
                        sb.AppendLine(@"Connection: Upgrade");
                        sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                        sb.AppendLine(@"Sec-WebSocket-Protocol: superchat");
                        sb.AppendLine(@"Sec-WebSocket-Extensions: test-extension;optionA");
                        sb.AppendLine();

                        using (var sr = new StreamReader(connectionOutput))
                        {
                            var s = sr.ReadToEnd();
                            Assert.Equal(sb.ToString(), s);
                        }
                    }
        }
Exemple #29
0
        public void WebSocketHandshaker_CanNegotiateAnExtensionWithParameters()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            WebSocketExtension ext = new WebSocketExtension("test-extension", new List <WebSocketExtensionOption>(new [] { new WebSocketExtensionOption()
                                                                                                                           {
                                                                                                                               ClientAvailableOption = false, Name = "optionA"
                                                                                                                           } }));
            IWebSocketMessageExtensionContext ctx;

            extension.Setup(x => x.TryNegotiate(It.IsAny <WebSocketHttpRequest>(), out ext, out ctx))
            .Returns(true);

            var factory = new WebSocketFactoryRfc6455();

            factory.MessageExtensions.RegisterExtension(extension.Object);
            var factories = new WebSocketFactoryCollection();

            factories.RegisterStandard(factory);
            WebSocketHandshaker handshaker = new WebSocketHandshaker(factories, new WebSocketListenerOptions()
            {
                SubProtocols = new[] { "superchat" }
            });

            using (var ms = new MemoryStream())
            {
                using (var sw = new StreamWriter(ms, Encoding.ASCII, 1024, true))
                {
                    sw.WriteLine(@"GET /chat HTTP/1.1");
                    sw.WriteLine(@"Host: server.example.com");
                    sw.WriteLine(@"Upgrade: websocket");
                    sw.WriteLine(@"Connection: Upgrade");
                    sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;");
                    sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==");
                    sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat");
                    sw.WriteLine(@"Sec-WebSocket-Extensions: test-extension;optionA");
                    sw.WriteLine(@"Sec-WebSocket-Version: 13");
                    sw.WriteLine(@"Origin: http://example.com");
                }

                var position = ms.Position;
                ms.Seek(0, SeekOrigin.Begin);

                var result = handshaker.HandshakeAsync(ms).Result;
                Assert.IsNotNull(result);
                Assert.IsTrue(result.IsWebSocketRequest);
                Assert.AreEqual(new Uri("http://example.com"), result.Request.Headers.Origin);
                Assert.AreEqual("superchat", result.Response.WebSocketProtocol);

                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 101 Switching Protocols");
                sb.AppendLine(@"Upgrade: websocket");
                sb.AppendLine(@"Connection: Upgrade");
                sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=");
                sb.AppendLine(@"Sec-WebSocket-Protocol: superchat");
                sb.AppendLine(@"Sec-WebSocket-Extensions: test-extension;optionA");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }