public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions options)
        {
            Guard.ParameterCannotBeNull(standards, "standards");
            Guard.ParameterCannotBeNull(extensions, "extensions");
            Guard.ParameterCannotBeNull(options, "options");

            _options = options;
            _extensions = extensions;
            _cancel = new CancellationTokenSource();
            _semaphore = new SemaphoreSlim(options.ParallelNegotiations);
            
            _sockets = new BufferBlock<Socket>(new DataflowBlockOptions()
            {
                BoundedCapacity = options.NegotiationQueueCapacity,
                CancellationToken = _cancel.Token
            });

            _negotiations = new BufferBlock<WebSocketNegotiationResult>(new DataflowBlockOptions()
            {
                BoundedCapacity = options.NegotiationQueueCapacity,
                CancellationToken = _cancel.Token,
            });

            _cancel.Token.Register(_sockets.Complete);
            _cancel.Token.Register(_negotiations.Complete);

            _handShaker = new WebSocketHandshaker(standards, _options);

            Task.Run((Func<Task>)WorkAsync);
        }
Exemple #2
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);
                        }
                    }
        }
        public void WebSocketHandshaker_CanReturnCookies()
        {
            WebSocketHandshaker handshaker = new WebSocketHandshaker(_factories,
                                                                     new WebSocketListenerOptions()
            {
                OnHttpNegotiation = (request, response) =>
                {
                    response.Cookies.Add(new Cookie("name1", "value1"));
                    response.Cookies.Add(new Cookie("name2", "value2"));
                }
            });

            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.NotNull(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 #4
0
        public void WebSocketHandshaker_CanDoSimpleHandshake()
        {
            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).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[0];
                Assert.AreEqual("key", cookie.Name);
                Assert.AreEqual(@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", cookie.Value);

                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 #5
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_DoesNotFailWhenSubProtocolRequestedButNotOffered()
        {
            var config = new WebSocketListenerConfig(new WebSocketListenerOptions());

            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);

                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 #7
0
        public void DoNotFailWhenSubProtocolRequestedButNotOffered()
        {
            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-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);

                        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_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 #9
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 #10
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 #11
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 #12
0
        WebSocketHandshake GenerateSimpleHandshake()
        {
            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(@"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);
            }
        }
Exemple #13
0
        public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions options)
        {
            if (standards == null)
            {
                throw new ArgumentNullException(nameof(standards));
            }
            if (extensions == null)
            {
                throw new ArgumentNullException(nameof(extensions));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            this.log = options.Logger;

            _options    = options;
            _extensions = extensions;
            _cancel     = new CancellationTokenSource();
            _semaphore  = new SemaphoreSlim(options.ParallelNegotiations);

            _connections  = new AsyncQueue <NetworkConnection>(options.NegotiationQueueCapacity);
            _negotiations = new AsyncQueue <WebSocketNegotiationResult>();
            _negotiations.ParallelTakeErrorMessage = $"Parallel call to '{nameof(WebSocketListener.AcceptWebSocketAsync)}' is not allowed.";
            _negotiations.ClosedErrorMessage       = $"{nameof(WebSocketListener)} is closed and will not accept new connections.";

            //_cancel.Token.Register(() => this._connections.Close(new OperationCanceledException()));

            _handShaker = new WebSocketHandshaker(standards, _options);

            if (options.PingMode != PingMode.Manual)
            {
                this.pingQueue = new PingQueue(options.PingInterval);
            }

            WorkAsync().LogFault(this.log);
        }
Exemple #14
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 #15
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 #16
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 #17
0
        public void FailWhenBadRequest()
        {
            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-Protoco");
                        }

                        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 #18
0
        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 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;;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);
                }
            }
        }
        public void WebSocketHandshaker_CanNegotiateAnExtension()
        {
            var extension = new Mock <IWebSocketMessageExtension>();

            extension.Setup(x => x.Name).Returns("test-extension");
            WebSocketExtension ext = new WebSocketExtension("test-extension");
            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");
                    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.True(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");
                sb.AppendLine();

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