public async Task WebSocketDisposalThrowsOnPeer() { // Arrange RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { var websocket = await ctx.WebSockets.AcceptWebSocketAsync(); websocket.Dispose(); } }; var builder = new WebHostBuilder().Configure(app => { app.Run(appDelegate); }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); var clientSocket = await client.ConnectAsync(new System.Uri("http://localhost"), CancellationToken.None); var buffer = new byte[1024]; await Assert.ThrowsAsync<IOException>(async () => await clientSocket.ReceiveAsync(new System.ArraySegment<byte>(buffer), CancellationToken.None)); clientSocket.Dispose(); }
public async Task WebSocketSubProtocolsWorks() { // Arrange RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { if (ctx.WebSockets.WebSocketRequestedProtocols.Contains("alpha") && ctx.WebSockets.WebSocketRequestedProtocols.Contains("bravo")) { // according to rfc6455, the "server needs to include the same field and one of the selected subprotocol values" // however, this isn't enforced by either our server or client so it's possible to accept an arbitrary protocol. // Done here to demonstrate not "correct" behaviour, simply to show it's possible. Other clients may not allow this. var websocket = await ctx.WebSockets.AcceptWebSocketAsync("charlie"); await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None); } else { var subprotocols = ctx.WebSockets.WebSocketRequestedProtocols.Any() ? string.Join(", ", ctx.WebSockets.WebSocketRequestedProtocols) : "<none>"; var closeReason = "Unexpected subprotocols: " + subprotocols; var websocket = await ctx.WebSockets.AcceptWebSocketAsync(); await websocket.CloseAsync(WebSocketCloseStatus.InternalServerError, closeReason, CancellationToken.None); } } }; var builder = new WebHostBuilder() .Configure(app => { app.Run(appDelegate); }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); client.SubProtocols.Add("alpha"); client.SubProtocols.Add("bravo"); var clientSocket = await client.ConnectAsync(new Uri("wss://localhost"), CancellationToken.None); var buffer = new byte[1024]; var result = await clientSocket.ReceiveAsync(new ArraySegment <byte>(buffer), CancellationToken.None); // Assert Assert.Equal(WebSocketMessageType.Close, result.MessageType); Assert.Equal("Normal Closure", result.CloseStatusDescription); Assert.Equal(WebSocketState.CloseReceived, clientSocket.State); Assert.Equal("charlie", clientSocket.SubProtocol); clientSocket.Dispose(); }
public async Task WebSocketAcceptThrowsWhenCancelled() { // Arrange // This logger will attempt to access information from HttpRequest once the HttpContext is created var logger = new VerifierLogger(); RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { var websocket = await ctx.WebSockets.AcceptWebSocketAsync(); var receiveArray = new byte[1024]; while (true) { var receiveResult = await websocket.ReceiveAsync(new System.ArraySegment <byte>(receiveArray), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None); break; } else { var sendBuffer = new System.ArraySegment <byte>(receiveArray, 0, receiveResult.Count); await websocket.SendAsync(sendBuffer, receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None); } } } }; var builder = new WebHostBuilder() .ConfigureServices(services => { services.AddSingleton <ILogger <IWebHost> >(logger); }) .Configure(app => { app.Run(appDelegate); }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); var tokenSource = new CancellationTokenSource(); tokenSource.Cancel(); // Assert await Assert.ThrowsAnyAsync <OperationCanceledException>(async() => await client.ConnectAsync(new System.Uri("http://localhost"), tokenSource.Token)); }
public async Task WebSocketTinyReceiveGeneratesEndOfMessage() { // Arrange RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { var websocket = await ctx.WebSockets.AcceptWebSocketAsync(); var receiveArray = new byte[1024]; while (true) { var receiveResult = await websocket.ReceiveAsync(new System.ArraySegment <byte>(receiveArray), CancellationToken.None); var sendBuffer = new System.ArraySegment <byte>(receiveArray, 0, receiveResult.Count); await websocket.SendAsync(sendBuffer, receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None); } } }; var builder = new WebHostBuilder().Configure(app => { app.Run(appDelegate); }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); var clientSocket = await client.ConnectAsync(new System.Uri("http://localhost"), CancellationToken.None); var hello = Encoding.UTF8.GetBytes("hello"); await clientSocket.SendAsync(new System.ArraySegment <byte>(hello), WebSocketMessageType.Text, true, CancellationToken.None); // Assert var buffer = new byte[1]; for (var i = 0; i < hello.Length; i++) { bool last = i == (hello.Length - 1); var result = await clientSocket.ReceiveAsync(new System.ArraySegment <byte>(buffer), CancellationToken.None); Assert.Equal(buffer.Length, result.Count); Assert.Equal(buffer[0], hello[i]); Assert.Equal(last, result.EndOfMessage); } clientSocket.Dispose(); }
public async Task WebSocketWorks() { // Arrange // This logger will attempt to access information from HttpRequest once the HttpContext is created var logger = new VerifierLogger(); RequestDelegate appDelegate = async ctx => { if (ctx.WebSockets.IsWebSocketRequest) { var websocket = await ctx.WebSockets.AcceptWebSocketAsync(); var receiveArray = new byte[1024]; while (true) { var receiveResult = await websocket.ReceiveAsync(new System.ArraySegment <byte>(receiveArray), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None); break; } else { var sendBuffer = new System.ArraySegment <byte>(receiveArray, 0, receiveResult.Count); await websocket.SendAsync(sendBuffer, receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None); } } } }; var builder = new WebHostBuilder() .ConfigureServices(services => { services.AddSingleton <ILogger <IWebHost> >(logger); }) .Configure(app => { app.Run(appDelegate); }); var server = new TestServer(builder); // Act var client = server.CreateWebSocketClient(); // The HttpContext will be created and the logger will make sure that the HttpRequest exists and contains reasonable values var clientSocket = await client.ConnectAsync(new System.Uri("http://localhost"), CancellationToken.None); var hello = Encoding.UTF8.GetBytes("hello"); await clientSocket.SendAsync(new System.ArraySegment <byte>(hello), WebSocketMessageType.Text, true, CancellationToken.None); var world = Encoding.UTF8.GetBytes("world!"); await clientSocket.SendAsync(new System.ArraySegment <byte>(world), WebSocketMessageType.Binary, true, CancellationToken.None); await clientSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Normal Closure", CancellationToken.None); // Assert Assert.Equal(WebSocketState.CloseSent, clientSocket.State); var buffer = new byte[1024]; var result = await clientSocket.ReceiveAsync(new System.ArraySegment <byte>(buffer), CancellationToken.None); Assert.Equal(hello.Length, result.Count); Assert.True(hello.SequenceEqual(buffer.Take(hello.Length))); Assert.Equal(WebSocketMessageType.Text, result.MessageType); result = await clientSocket.ReceiveAsync(new System.ArraySegment <byte>(buffer), CancellationToken.None); Assert.Equal(world.Length, result.Count); Assert.True(world.SequenceEqual(buffer.Take(world.Length))); Assert.Equal(WebSocketMessageType.Binary, result.MessageType); result = await clientSocket.ReceiveAsync(new System.ArraySegment <byte>(buffer), CancellationToken.None); Assert.Equal(WebSocketMessageType.Close, result.MessageType); Assert.Equal(WebSocketState.Closed, clientSocket.State); clientSocket.Dispose(); }