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