コード例 #1
0
            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();
                }
            }
コード例 #2
0
            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()));
                    }
                }
            }
コード例 #3
0
            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();
                }
            }
コード例 #4
0
            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);
                }
            }
コード例 #5
0
            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)));
                }
            }
コード例 #6
0
            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());
                }
            }
コード例 #7
0
            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);
                    }));
                }
            }
コード例 #8
0
            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()));
                }
            }
コード例 #9
0
            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));
                }
            }
コード例 #10
0
            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);
                }
            }
コード例 #11
0
            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();
                }
            }
コード例 #12
0
            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);
                }
            }
コード例 #13
0
            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);
                    }
                }
            }