public async Task SendReceiveFrames() { using (var pair = WebSocketPair.Create()) { var client = pair.ClientSocket.ExecuteAsync(_ => { Assert.False(true, "did not expect the client to receive any frames!"); return(Task.CompletedTask); }); // Send Frames await pair.ClientSocket.SendAsync(CreateTextFrame("Hello")).OrTimeout(); await pair.ClientSocket.SendAsync(CreateTextFrame("World")).OrTimeout(); await pair.ClientSocket.SendAsync(CreateBinaryFrame(new byte[] { 0xDE, 0xAD, 0xBE, 0xEF })).OrTimeout(); await pair.ClientSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure)).OrTimeout(); var summary = await pair.ServerSocket.ExecuteAndCaptureFramesAsync().OrTimeout(); Assert.Equal(3, summary.Received.Count); Assert.Equal("Hello", Encoding.UTF8.GetString(summary.Received[0].Payload.ToArray())); Assert.Equal("World", Encoding.UTF8.GetString(summary.Received[1].Payload.ToArray())); Assert.Equal(new byte[] { 0xDE, 0xAD, 0xBE, 0xEF }, summary.Received[2].Payload.ToArray()); await pair.ServerSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure)).OrTimeout(); await client.OrTimeout(); } }
public async Task ValidSingleFramePayloads(byte[] payload, string decoded) { using (var pair = WebSocketPair.Create()) { var timeoutToken = TestUtil.CreateTimeoutToken(); using (timeoutToken.Register(() => pair.Dispose())) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var serverSummary = await server.OrTimeout(); await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var clientSummary = await client.OrTimeout(); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(1, serverSummary.Received.Count); Assert.True(serverSummary.Received[0].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, serverSummary.Received[0].Opcode); Assert.Equal(decoded, Encoding.UTF8.GetString(serverSummary.Received[0].Payload.ToArray())); } } }
public async Task TerminatesConnectionOnUnsolicitedContinuationFrame() { // Arrange using (var pair = WebSocketPair.Create( serverOptions: new WebSocketOptions().WithAllFramesPassedThrough(), clientOptions: new WebSocketOptions().WithAllFramesPassedThrough())) { var payload = Encoding.UTF8.GetBytes("hello"); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); // Act await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : true, opcode : WebSocketOpcode.Text, payload : ReadableBuffer.Create(payload))); await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : true, opcode : WebSocketOpcode.Continuation, payload : ReadableBuffer.Create(payload))); // Server should terminate var clientSummary = await client.OrTimeout(); Assert.Equal(WebSocketCloseStatus.ProtocolError, clientSummary.CloseResult.Status); Assert.Equal("Continuation Frame was received when expecting a new message", clientSummary.CloseResult.Description); await server.OrTimeout(); } }
public async Task AbnormalTerminationOfInboundChannelCausesExecuteToThrow() { using (var pair = WebSocketPair.Create()) { var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); pair.TerminateFromClient(new InvalidOperationException("It broke!")); await Assert.ThrowsAsync <InvalidOperationException>(() => server); } }
public async Task StateTransitions() { using (var pair = WebSocketPair.Create()) { // Initial State Assert.Equal(WebSocketConnectionState.Created, pair.ServerSocket.State); Assert.Equal(WebSocketConnectionState.Created, pair.ClientSocket.State); // Start the sockets var serverReceiving = new TaskCompletionSource <object>(); var clientReceiving = new TaskCompletionSource <object>(); var server = pair.ServerSocket.ExecuteAsync(frame => serverReceiving.TrySetResult(null)); var client = pair.ClientSocket.ExecuteAsync(frame => clientReceiving.TrySetResult(null)); // Send a frame from each and verify that the state transitioned. // We need to do this because it's the only way to correctly wait for the state transition (which happens asynchronously in ExecuteAsync) await pair.ClientSocket.SendAsync(CreateTextFrame("Hello")).OrTimeout(); await pair.ServerSocket.SendAsync(CreateTextFrame("Hello")).OrTimeout(); await Task.WhenAll(serverReceiving.Task, clientReceiving.Task).OrTimeout(); // Check state Assert.Equal(WebSocketConnectionState.Connected, pair.ServerSocket.State); Assert.Equal(WebSocketConnectionState.Connected, pair.ClientSocket.State); // Close the server socket await pair.ServerSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure)).OrTimeout(); await client.OrTimeout(); // Check state Assert.Equal(WebSocketConnectionState.CloseSent, pair.ServerSocket.State); Assert.Equal(WebSocketConnectionState.CloseReceived, pair.ClientSocket.State); // Close the client socket await pair.ClientSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure)).OrTimeout(); await server.OrTimeout(); // Check state Assert.Equal(WebSocketConnectionState.Closed, pair.ServerSocket.State); Assert.Equal(WebSocketConnectionState.Closed, pair.ClientSocket.State); // Verify we can't restart the connection or send a message await Assert.ThrowsAsync <ObjectDisposedException>(async() => await pair.ServerSocket.ExecuteAsync(f => { })); await Assert.ThrowsAsync <ObjectDisposedException>(async() => await pair.ClientSocket.SendAsync(CreateTextFrame("Nope"))); await Assert.ThrowsAsync <ObjectDisposedException>(async() => await pair.ClientSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure))); } }
public async Task AutomaticPingResponse() { // Arrange using (var pair = WebSocketPair.Create( serverOptions: new WebSocketOptions().WithAllFramesPassedThrough(), clientOptions: new WebSocketOptions().WithAllFramesPassedThrough())) { var payload = Encoding.UTF8.GetBytes("ping payload"); var pongTcs = new TaskCompletionSource <WebSocketFrame>(); var client = pair.ClientSocket.ExecuteAsync(f => { if (f.Opcode == WebSocketOpcode.Pong) { pongTcs.TrySetResult(f.Copy()); } else { Assert.False(true, "Received non-pong frame from server!"); } }); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); // Act await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : true, opcode : WebSocketOpcode.Ping, payload : ReadableBuffer.Create(payload))); var pongFrame = await pongTcs.Task.OrTimeout(); await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); await server.OrTimeout(); await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); await client.OrTimeout(); // Assert Assert.True(pongFrame.EndOfMessage); Assert.Equal(WebSocketOpcode.Pong, pongFrame.Opcode); Assert.Equal(payload, pongFrame.Payload.ToArray()); } }
public async Task AutomaticPingTransmission() { var startTime = DateTime.UtcNow; // Arrange using (var pair = WebSocketPair.Create( serverOptions: new WebSocketOptions().WithAllFramesPassedThrough().WithPingInterval(TimeSpan.FromMilliseconds(100)), clientOptions: new WebSocketOptions().WithAllFramesPassedThrough())) { var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); // Act // Wait for pings to be sent await Task.Delay(200); await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var clientSummary = await client.OrTimeout(); await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var serverSummary = await server.OrTimeout(); // Assert Assert.NotEqual(0, clientSummary.Received.Count); Assert.True(clientSummary.Received.All(f => f.EndOfMessage)); Assert.True(clientSummary.Received.All(f => f.Opcode == WebSocketOpcode.Ping)); Assert.True(clientSummary.Received.All(f => { var str = Encoding.UTF8.GetString(f.Payload.ToArray()); // We can't verify the exact timestamp, but we can verify that it is a timestamp created after we started. DateTime dt; if (DateTime.TryParseExact(str, "O", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out dt)) { return(dt >= startTime); } return(false); })); } }
public async Task CanReceiveControlFrameInTheMiddleOfFragmentedMessage() { using (var pair = WebSocketPair.Create()) { // Start the sockets var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); // Send (Fin=false, "Hello"), (Ping), (Fin=true, "World") await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : false, opcode : WebSocketOpcode.Text, payload : ReadableBuffer.Create(Encoding.UTF8.GetBytes("Hello")))); await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : true, opcode : WebSocketOpcode.Ping, payload : ReadableBuffer.Create(Encoding.UTF8.GetBytes("ping")))); await pair.ClientSocket.SendAsync(new WebSocketFrame( endOfMessage : true, opcode : WebSocketOpcode.Continuation, payload : ReadableBuffer.Create(Encoding.UTF8.GetBytes("World")))); // Close the socket await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure); var serverSummary = await server; await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure); var clientSummary = await client; // Assert var nonControlFrames = serverSummary.Received.Where(f => f.Opcode < WebSocketOpcode.Close).ToList(); Assert.Equal(2, nonControlFrames.Count); Assert.False(nonControlFrames[0].EndOfMessage); Assert.True(nonControlFrames[1].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, nonControlFrames[0].Opcode); Assert.Equal(WebSocketOpcode.Continuation, nonControlFrames[1].Opcode); Assert.Equal("Hello", Encoding.UTF8.GetString(nonControlFrames[0].Payload.ToArray())); Assert.Equal("World", Encoding.UTF8.GetString(nonControlFrames[1].Payload.ToArray())); } }
public async Task ValidMultiFramePayloads(byte[] payload1, byte[] payload2, string decoded) { using (var pair = WebSocketPair.Create()) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: false, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload1)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Continuation, payload: ReadableBuffer.Create(payload2)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); await pair.ClientSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var serverSummary = await server.OrTimeout(); await pair.ServerSocket.CloseAsync(WebSocketCloseStatus.NormalClosure).OrTimeout(); var clientSummary = await client.OrTimeout(); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(2, serverSummary.Received.Count); Assert.False(serverSummary.Received[0].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, serverSummary.Received[0].Opcode); Assert.True(serverSummary.Received[1].EndOfMessage); Assert.Equal(WebSocketOpcode.Continuation, serverSummary.Received[1].Opcode); var finalPayload = serverSummary.Received.SelectMany(f => f.Payload.ToArray()).ToArray(); Assert.Equal(decoded, Encoding.UTF8.GetString(finalPayload)); } }
public async Task ExecuteReturnsWhenCloseFrameReceived() { using (var pair = WebSocketPair.Create()) { var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); await pair.ClientSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.InvalidMessageType, "Abc")).OrTimeout(); var serverSummary = await pair.ServerSocket.ExecuteAndCaptureFramesAsync().OrTimeout(); await pair.ServerSocket.CloseAsync(new WebSocketCloseResult(WebSocketCloseStatus.NormalClosure, "Ok")).OrTimeout(); var clientSummary = await client.OrTimeout(); Assert.Equal(0, serverSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.InvalidMessageType, serverSummary.CloseResult.Status); Assert.Equal("Abc", serverSummary.CloseResult.Description); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.NormalClosure, clientSummary.CloseResult.Status); Assert.Equal("Ok", clientSummary.CloseResult.Description); } }
private static async Task WriteFrameAndExpectClose(byte[] rawFrame, WebSocketCloseStatus closeStatus, string closeReason) { // Arrange using (var pair = WebSocketPair.Create( serverOptions: new WebSocketOptions().WithAllFramesPassedThrough(), clientOptions: new WebSocketOptions().WithAllFramesPassedThrough())) { var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); // Act await pair.ClientToServer.WriteAsync(rawFrame); // Server should terminate var clientSummary = await client.OrTimeout(); Assert.Equal(closeStatus, clientSummary.CloseResult.Status); Assert.Equal(closeReason, clientSummary.CloseResult.Description); await server.OrTimeout(); } }
public async Task InvalidSingleFramePayloads(byte[] payload) { using (var pair = WebSocketPair.Create()) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); var clientSummary = await client.OrTimeout(); var serverSummary = await server.OrTimeout(); Assert.Equal(0, serverSummary.Received.Count); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.InvalidPayloadData, clientSummary.CloseResult.Status); Assert.Equal("An invalid Text frame payload was received", clientSummary.CloseResult.Description); } }
public async Task InvalidMultiFramePayloads(byte[] payload1, byte[] payload2) { using (var pair = WebSocketPair.Create()) { var timeoutToken = TestUtil.CreateTimeoutToken(); using (timeoutToken.Register(() => pair.Dispose())) { var server = pair.ServerSocket.ExecuteAndCaptureFramesAsync(); var client = pair.ClientSocket.ExecuteAndCaptureFramesAsync(); var frame = new WebSocketFrame( endOfMessage: false, opcode: WebSocketOpcode.Text, payload: ReadableBuffer.Create(payload1)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); frame = new WebSocketFrame( endOfMessage: true, opcode: WebSocketOpcode.Continuation, payload: ReadableBuffer.Create(payload2)); await pair.ClientSocket.SendAsync(frame).OrTimeout(); var clientSummary = await client.OrTimeout(); var serverSummary = await server.OrTimeout(); Assert.Equal(1, serverSummary.Received.Count); Assert.False(serverSummary.Received[0].EndOfMessage); Assert.Equal(WebSocketOpcode.Text, serverSummary.Received[0].Opcode); Assert.Equal(payload1, serverSummary.Received[0].Payload.ToArray()); Assert.Equal(0, clientSummary.Received.Count); Assert.Equal(WebSocketCloseStatus.InvalidPayloadData, clientSummary.CloseResult.Status); Assert.Equal("An invalid Text frame payload was received", clientSummary.CloseResult.Description); } } }