예제 #1
0
        public WebSocketListener(IPEndPoint endpoint, WebSocketListenerOptions options)
        {
            Guard.ParameterCannotBeNull(endpoint, "endpoint");
            Guard.ParameterCannotBeNull(options, "options");
            
            options.CheckCoherence();
            _options = options.Clone();
            _cancel = new CancellationTokenSource();

#if NETSTANDARD || UAP
            _listener = new TcpListener(endpoint);
#else
            if (Type.GetType("Mono.Runtime") == null && _options.UseDualStackSocket)
                _listener = TcpListener.Create(endpoint.Port);
            else
                _listener = new TcpListener(endpoint);
#endif

            if (_options.UseNagleAlgorithm.HasValue)
                _listener.Server.NoDelay = !_options.UseNagleAlgorithm.Value;

            ConnectionExtensions = new WebSocketConnectionExtensionCollection(this);
            Standards = new WebSocketFactoryCollection(this);

            _negotiationQueue = new HttpNegotiationQueue(Standards, ConnectionExtensions, options);
        }
예제 #2
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);
                        }
                    }
        }
        public HttpNegotiationQueue(WebSocketFactoryCollection standards, WebSocketConnectionExtensionCollection extensions, WebSocketListenerOptions 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);
        }
        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);
        }
예제 #5
0
        public void With_WebSocket_CanWriteStringAsync()
        {
            var factories = new WebSocketFactoryCollection();

            factories.RegisterStandard(new WebSocketFactoryRfc6455());

            CancellationToken cancellationToken = CancellationToken.None;
            string            msg = "01";
            var handshake         = GenerateSimpleHandshake(factories);
            var ms = new MemoryStream();

            using (WebSocket ws = new WebSocketRfc6455(
                       ms,
                       new WebSocketListenerOptions {
                PingTimeout = Timeout.InfiniteTimeSpan
            },
                       new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1),
                       new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2),
                       handshake.Request,
                       handshake.Response,
                       handshake.NegotiatedMessageExtensions))
            {
                ws.WriteStringAsync(msg, cancellationToken).Wait(cancellationToken);
            }

            Assert.Equal(new byte[] { 1, 2, 48, 49, 128, 0, 136, 2, 3, 232 }, ms.ToArray());
        }
예제 #6
0
        public static void Main(string[] args)
        {
            _factories = new WebSocketFactoryCollection();
            _factories.RegisterStandard(new WebSocketFactoryRfc6455());

            With_WebSocket_CanWriteString();
            With_WebSocket_CanWriteStringAsync();
        }
        public WebSocketHandshaker(WebSocketFactoryCollection factories, WebSocketListenerOptions options)
        {
            Guard.ParameterCannotBeNull(factories, "factories");
            Guard.ParameterCannotBeNull(options, "options");

            _factories = factories;
            _options = options;
        }
예제 #8
0
        public void WebSocketHandshaker_FailsWhenBadRequest()
        {
            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-Protoco");
                }

                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);
                }
            }
        }
예제 #9
0
        public With_HttpFallback()
        {
            _factories = new WebSocketFactoryCollection();
            _factories.RegisterStandard(new WebSocketFactoryRfc6455());

            _fallback = new Mock <IHttpFallback>();
            _fallback.Setup(x => x.Post(It.IsAny <HttpRequest>(), It.IsAny <Stream>()))
            .Callback((HttpRequest r, Stream s) => _postedConnections.Add(new Tuple <HttpRequest, Stream>(r, s)));
            _postedConnections = new List <Tuple <HttpRequest, Stream> >();
        }
        public WebSocketHandshaker(WebSocketFactoryCollection factories, WebSocketListenerOptions options)
        {
            if (factories == null)
                throw new ArgumentNullException("factories");

            if (options == null)
                throw new ArgumentNullException("options");

            _factories = factories;
            _options = options;
        }
예제 #11
0
        public HttpFallbackTests(ITestOutputHelper output)
        {
            this.logger    = new TestLogger(output);
            this.factories = new WebSocketFactoryCollection();
            this.factories.Add(new WebSocketFactoryRfc6455());

            this.fallback = new Mock <IHttpFallback>();
            this.fallback.Setup(x => x.Post(It.IsAny <IHttpRequest>(), It.IsAny <NetworkConnection>()))
            .Callback((IHttpRequest r, NetworkConnection s) => this.postedConnections.Add(new Tuple <IHttpRequest, NetworkConnection>(r, s)));
            this.postedConnections = new List <Tuple <IHttpRequest, NetworkConnection> >();
        }
        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.NotNull(result);
                Assert.False(result.IsWebSocketRequest);
                Assert.False(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);
                }
            }
        }
예제 #13
0
        public WebSocketTests(ITestOutputHelper output)
        {
            var logger = new TestLogger(output);

            this.factories = new WebSocketFactoryCollection();
            this.factories.Add(new WebSocketFactoryRfc6455());
            this.options = new WebSocketListenerOptions
            {
                Logger         = logger,
                PingTimeout    = Timeout.InfiniteTimeSpan,
                BufferManager  = BufferManager.CreateBufferManager(10, 1024),
                SendBufferSize = 512
            };
        }
        public static WebSocketFactoryCollection RegisterRfc6455(this WebSocketFactoryCollection collection, Action <WebSocketFactoryRfc6455> configure = null)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            var factory = new WebSocketFactoryRfc6455();

            configure?.Invoke(factory);

            collection.Add(factory);

            return(collection);
        }
        public WebSocketListener(IPEndPoint endpoint, WebSocketListenerOptions options)
        {
            Guard.ParameterCannotBeNull(endpoint, "endpoint");
            Guard.ParameterCannotBeNull(options, "options");
            
            options.CheckCoherence();
            _options = options.Clone();
            _cancel = new CancellationTokenSource();

            _listener = new TcpListener(endpoint);
            if(_options.UseNagleAlgorithm.HasValue)
                _listener.Server.NoDelay = !_options.UseNagleAlgorithm.Value;

            ConnectionExtensions = new WebSocketConnectionExtensionCollection(this);
            Standards = new WebSocketFactoryCollection(this);

            _negotiationQueue = new HttpNegotiationQueue(Standards, ConnectionExtensions, options);
        }
        public WebSocketListener(IPEndPoint endpoint, WebSocketListenerOptions options)
        {
            if (options == null)
                throw new ArgumentNullException("options");

            if (endpoint == null)
                throw new ArgumentNullException("endpoint");

            _options = options.Clone();
            _cancel = new CancellationTokenSource();
            _listener = new TcpListener(endpoint);
            
            ConnectionExtensions = new WebSocketConnectionExtensionCollection(this);
            Standards = new WebSocketFactoryCollection(this);
            Func<Socket, Task<WebSocketNegotiationResult>> negotiate = NegotiateWebSocket;
            _negotiationQueue = new TransformBlock<Socket, WebSocketNegotiationResult>(negotiate, new ExecutionDataflowBlockOptions() { CancellationToken = _cancel.Token, MaxDegreeOfParallelism = options.ParallelNegotiations, BoundedCapacity = options.NegotiationQueueCapacity });

            _handShaker = new WebSocketHandshaker(Standards, _options);
        }
예제 #17
0
        public WebSocketListener(IPEndPoint endpoint, WebSocketListenerOptions options)
        {
            if (options == null)
                throw new ArgumentNullException("options");

            if (endpoint == null)
                throw new ArgumentNullException("endpoint");
            
            options.CheckCoherence();
            _options = options.Clone();
            _cancel = new CancellationTokenSource();

            _listener = new TcpListener(endpoint);
            if(_options.UseNagleAlgorithm.HasValue)
                _listener.Server.NoDelay = !_options.UseNagleAlgorithm.Value;

            ConnectionExtensions = new WebSocketConnectionExtensionCollection(this);
            Standards = new WebSocketFactoryCollection(this);

            _negotiationQueue = new HttpNegotiationQueue(Standards, ConnectionExtensions, options);
        }
예제 #18
0
        private WebSocketHandshake GenerateSimpleHandshake(WebSocketFactoryCollection factories)
        {
            var 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);
            }
        }
예제 #19
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);
        }
예제 #20
0
 public With_WebSocket()
 {
     _factories = new WebSocketFactoryCollection();
     _factories.RegisterStandard(new WebSocketFactoryRfc6455());
 }
        public void WebSocketHandshaker_CanIndicateANonSupportedVersion()
        {
            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: 14");
                    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.IsFalse(result.IsVersionSupported);
                ms.Seek(position, SeekOrigin.Begin);

                StringBuilder sb = new StringBuilder();
                sb.AppendLine(@"HTTP/1.1 426 Upgrade Required");
                sb.AppendLine(@"Sec-WebSocket-Version: 13");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
예제 #22
0
 public WebSocketHandshakerTests(ITestOutputHelper output)
 {
     this.logger    = new TestLogger(output);
     this.factories = new WebSocketFactoryCollection();
     this.factories.Add(new WebSocketFactoryRfc6455());
 }
 public With_WebSocketHandshaker()
 {
     _factories = new WebSocketFactoryCollection();
     _factories.RegisterStandard(new WebSocketFactoryRfc6455());
 }
        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 404 Bad Request");
                sb.AppendLine();

                using (var sr = new StreamReader(ms))
                {
                    var s = sr.ReadToEnd();
                    Assert.AreEqual(sb.ToString(), s);
                }
            }
        }
예제 #25
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);
                        }
                    }
        }
        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);
                }
            }
        }
예제 #27
0
        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.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");
                sb.AppendLine();

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