public void ReadTwoBufferedSmallFrames() { var handshake = this.GenerateSimpleHandshake(); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, this.options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { connectionInput.Write(new byte[] { 129, 130, 75, 91, 80, 26, 3, 50 }, 0, 8); connectionInput.Write(new byte[] { 129, 130, 75, 91, 80, 26, 3, 50 }, 0, 8); connectionInput.Flush(); connectionInput.Seek(0, SeekOrigin.Begin); var reader = ws.ReadMessageAsync(CancellationToken.None).Result; Assert.NotNull(reader); using (var sr = new StreamReader(reader, Encoding.UTF8, true, 1024, true)) { var s = sr.ReadToEnd(); Assert.Equal("Hi", s); } reader = ws.ReadMessageAsync(CancellationToken.None).Result; Assert.NotNull(reader); using (var sr = new StreamReader(reader, Encoding.UTF8, true, 1024, true)) { var s = sr.ReadToEndAsync().Result; Assert.Equal("Hi", s); } reader = ws.ReadMessageAsync(CancellationToken.None).Result; Assert.Null(reader); } }
public void DoSimpleHandshakeWithEndpoints() { var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions { Logger = this.logger }); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;"); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.Equal(connection.LocalEndPoint.ToString(), result.Request.LocalEndPoint.ToString()); Assert.Equal(connection.RemoteEndPoint.ToString(), result.Request.RemoteEndPoint.ToString()); } }
public void UnderstandEncodedCookies() { var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions { Logger = this.logger }); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: key=This%20is%20encoded."); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.NotNull(result); Assert.True((bool)result.IsValidWebSocketRequest); Assert.Equal(1, result.Request.Cookies.Count); Assert.Equal((string)"This is encoded.", (string)result.Request.Cookies["key"].Value); } }
public void ReadEmptyMessage() { var handshake = this.GenerateSimpleHandshake(); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, this.options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { connectionInput.Write(new byte[] { 129, 128, 166, 124, 106, 65 }, 0, 6); connectionInput.Flush(); connectionInput.Seek(0, SeekOrigin.Begin); var reader = ws.ReadMessageAsync(CancellationToken.None).Result; Assert.NotNull(reader); using (var sr = new StreamReader(reader, Encoding.UTF8, true, 1024, true)) { var s = sr.ReadToEnd(); Assert.Equal(string.Empty, s); } } }
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 void ParseMultipleCookie() { var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions { Logger = this.logger }); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: cookie1=uno; cookie2=dos"); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.NotNull(result); Assert.Equal(2, result.Request.Cookies.Count); } }
public void SimpleHandshakeIgnoringFallback() { var options = new WebSocketListenerOptions { Logger = this.logger }; options.HttpFallback = this.fallback.Object; var handshaker = new WebSocketHandshaker(this.factories, options); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;"); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.NotNull(result); Assert.True((bool)result.IsWebSocketRequest); Assert.True((bool)result.IsVersionSupported); Assert.Equal(new Uri("http://example.com"), new Uri(result.Request.Headers[RequestHeader.Origin])); Assert.Equal((string)"server.example.com", (string)result.Request.Headers[RequestHeader.Host]); Assert.Equal((string)@"/chat", (string)result.Request.RequestUri.ToString()); Assert.Equal(1, result.Request.Cookies.Count); var cookie = result.Request.Cookies["key"]; Assert.Equal((string)"key", (string)cookie.Name); Assert.Equal((string)@"W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5", (string)cookie.Value); Assert.NotNull(result.Request.LocalEndPoint); Assert.NotNull(result.Request.RemoteEndPoint); connectionOutput.Seek(0, SeekOrigin.Begin); var sb = new StringBuilder(); sb.AppendLine(@"HTTP/1.1 101 Switching Protocols"); sb.AppendLine(@"Upgrade: websocket"); sb.AppendLine(@"Connection: Upgrade"); sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk="); sb.AppendLine(); using (var sr = new StreamReader(connectionOutput)) { var s = sr.ReadToEnd(); Assert.Equal(sb.ToString(), s); } } }
public void DoesNotFailWhenSubProtocolRequestedButNoMatch() { var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions { Logger = this.logger, SubProtocols = new[] { "superchat2", "text" } }); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;"); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Protocol: chat, superchat"); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.NotNull(result); Assert.True((bool)result.IsWebSocketRequest); Assert.True((bool)result.IsVersionSupported); Assert.Null(result.Error); Assert.True((bool)result.IsValidWebSocketRequest); Assert.True(string.IsNullOrEmpty(result.Response.Headers[ResponseHeader.WebSocketProtocol])); connectionOutput.Seek(0, SeekOrigin.Begin); var sb = new StringBuilder(); sb.AppendLine(@"HTTP/1.1 101 Switching Protocols"); sb.AppendLine(@"Upgrade: websocket"); sb.AppendLine(@"Connection: Upgrade"); sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk="); sb.AppendLine(); using (var sr = new StreamReader(connectionOutput)) { var s = sr.ReadToEnd(); Assert.Equal(sb.ToString(), s); } } }
public void ReturnCookies() { var handshaker = new WebSocketHandshaker(this.factories, new WebSocketListenerOptions { Logger = this.logger, HttpAuthenticationHandler = async(request, response) => { response.Cookies.Add(new Cookie("name1", "value1")); response.Cookies.Add(new Cookie("name2", "value2")); return(true); } }); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) { using (var sw = new StreamWriter(connectionInput, Encoding.ASCII, 1024, true)) { sw.WriteLine(@"GET /chat HTTP/1.1"); sw.WriteLine(@"Host: server.example.com"); sw.WriteLine(@"Upgrade: websocket"); sw.WriteLine(@"Connection: Upgrade"); sw.WriteLine(@"Cookie: key=W9g/8FLW8RAFqSCWBvB9Ag==#5962c0ace89f4f780aa2a53febf2aae5;"); sw.WriteLine(@"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw=="); sw.WriteLine(@"Sec-WebSocket-Version: 13"); sw.WriteLine(@"Origin: http://example.com"); } connectionInput.Seek(0, SeekOrigin.Begin); var result = handshaker.HandshakeAsync(connection).Result; Assert.NotNull(result); connectionOutput.Seek(0, SeekOrigin.Begin); var sb = new StringBuilder(); sb.AppendLine(@"HTTP/1.1 101 Switching Protocols"); sb.AppendLine(@"Upgrade: websocket"); sb.AppendLine(@"Connection: Upgrade"); sb.AppendLine(@"Set-Cookie: name1=value1"); sb.AppendLine(@"Set-Cookie: name2=value2"); sb.AppendLine(@"Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk="); sb.AppendLine(); using (var sr = new StreamReader(connectionOutput)) { var s = sr.ReadToEnd(); Assert.Equal(sb.ToString(), s); } } }
public void WriteTwoSequentialMessages() { var handshake = this.GenerateSimpleHandshake(); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, this.options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { using (var writer = ws.CreateMessageWriter(WebSocketMessageType.Text)) { } using (var writer = ws.CreateMessageWriter(WebSocketMessageType.Text)) { } } }
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 FailDoubleMessageWrite() { var handshake = this.GenerateSimpleHandshake(); Assert.Throws <WebSocketException>(() => { using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, this.options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { var writer = ws.CreateMessageWriter(WebSocketMessageType.Text); writer = ws.CreateMessageWriter(WebSocketMessageType.Text); } }); }
public void DetectHalfOpenConnection() { var handshake = this.GenerateSimpleHandshake(); var options = this.options.Clone(); options.PingTimeout = TimeSpan.FromMilliseconds(100); using (var connectionInput = new MemoryStream()) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { ws.ReadMessageAsync(CancellationToken.None); // DateTime has no millisecond precision. Thread.Sleep(500); Assert.False(ws.IsConnected); } }
public async Task FailDoubleMessageAwait() { var handshake = this.GenerateSimpleHandshake(); await Assert.ThrowsAsync <WebSocketException>(async() => { using (var connectionInput = new BufferedStream(new MemoryStream())) using (var connectionOutput = new MemoryStream()) using (var connection = new DummyNetworkConnection(connectionInput, connectionOutput)) using (var ws = new WebSocketRfc6455(connection, this.options, handshake.Request, handshake.Response, handshake.NegotiatedMessageExtensions)) { connectionInput.Write(new byte[] { 129, 130, 75, 91, 80, 26, 3, 50 }, 0, 8); connectionInput.Write(new byte[] { 129, 130, 75, 91, 80, 26, 3, 50 }, 0, 8); connectionInput.Flush(); connectionInput.Seek(0, SeekOrigin.Begin); await ws.ReadMessageAsync(CancellationToken.None).ConfigureAwait(false); await ws.ReadMessageAsync(CancellationToken.None).ConfigureAwait(false); } }).ConfigureAwait(false); }
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); } }
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); } } }