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