示例#1
0
        public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWebSocketStateUpdated()
        {
            var options = new LoopbackServer.Options {
                WebSocketEndpoint = true
            };

            Func <ClientWebSocket, LoopbackServer, Uri, Task> connectToServerThatAbortsConnection = async(clientSocket, server, url) =>
            {
                var pendingReceiveAsyncPosted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

                // Start listening for incoming connections on the server side.
                Task acceptTask = server.AcceptConnectionAsync(async connection =>
                {
                    // Complete the WebSocket upgrade. After this is done, the client-side ConnectAsync should complete.
                    Assert.NotNull(await LoopbackHelper.WebSocketHandshakeAsync(connection));

                    // Wait for client-side ConnectAsync to complete and for a pending ReceiveAsync to be posted.
                    await pendingReceiveAsyncPosted.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeOutMilliseconds));

                    // Close the underlying connection prematurely (without sending a WebSocket Close frame).
                    connection.Socket.Shutdown(SocketShutdown.Both);
                    connection.Socket.Close();
                });

                // Initiate a connection attempt.
                var cts = new CancellationTokenSource(TimeOutMilliseconds);
                await clientSocket.ConnectAsync(url, cts.Token);

                // Post a pending ReceiveAsync before the TCP connection is torn down.
                var  recvBuffer          = new byte[100];
                var  recvSegment         = new ArraySegment <byte>(recvBuffer);
                Task pendingReceiveAsync = ReceiveAsync(clientSocket, recvSegment, cts.Token);
                pendingReceiveAsyncPosted.SetResult();

                // Wait for the server to close the underlying connection.
                await acceptTask.WaitAsync(cts.Token);

                WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync);

                Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode);

                if (PlatformDetection.IsInAppContainer)
                {
                    const uint WININET_E_CONNECTION_ABORTED = 0x80072EFE;

                    Assert.NotNull(pendingReceiveException.InnerException);
                    Assert.Equal(WININET_E_CONNECTION_ABORTED, (uint)pendingReceiveException.InnerException.HResult);
                }

                WebSocketException newReceiveException =
                    await Assert.ThrowsAsync <WebSocketException>(() => ReceiveAsync(clientSocket, recvSegment, cts.Token));

                Assert.Equal(
                    ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"),
                    newReceiveException.Message);

                Assert.Equal(WebSocketState.Aborted, clientSocket.State);
                Assert.Null(clientSocket.CloseStatus);
            };

            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                using (ClientWebSocket clientSocket = new ClientWebSocket())
                {
                    await connectToServerThatAbortsConnection(clientSocket, server, url);
                }
            }, options);
        }
示例#2
0
        public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWebSocketStateUpdated()
        {
            var options = new LoopbackServer.Options {
                WebSocketEndpoint = true
            };

            Func <ClientWebSocket, Socket, Uri, Task> connectToServerThatAbortsConnection = async(clientSocket, server, url) =>
            {
                AutoResetEvent pendingReceiveAsyncPosted = new AutoResetEvent(false);

                // Start listening for incoming connections on the server side.
                Task <List <string> > acceptTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) =>
                {
                    // Complete the WebSocket upgrade. After this is done, the client-side ConnectAsync should complete.
                    Assert.True(await LoopbackServer.WebSocketHandshakeAsync(socket, reader, writer));

                    // Wait for client-side ConnectAsync to complete and for a pending ReceiveAsync to be posted.
                    pendingReceiveAsyncPosted.WaitOne(TimeOutMilliseconds);

                    // Close the underlying connection prematurely (without sending a WebSocket Close frame).
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();

                    return(null);
                }, options);

                // Initiate a connection attempt.
                var cts = new CancellationTokenSource(TimeOutMilliseconds);
                await clientSocket.ConnectAsync(url, cts.Token);

                // Post a pending ReceiveAsync before the TCP connection is torn down.
                var  recvBuffer          = new byte[100];
                var  recvSegment         = new ArraySegment <byte>(recvBuffer);
                Task pendingReceiveAsync = clientSocket.ReceiveAsync(recvSegment, cts.Token);
                pendingReceiveAsyncPosted.Set();

                // Wait for the server to close the underlying connection.
                acceptTask.Wait(cts.Token);

                // Validate I/O errors and socket state.
                if (!PlatformDetection.IsWindows)
                {
                    _output.WriteLine("[Non-Windows] ManagedWebSocket-based implementation.");

                    WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync);

                    Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode);

                    WebSocketException newReceiveException =
                        await Assert.ThrowsAsync <WebSocketException>(() => clientSocket.ReceiveAsync(recvSegment, cts.Token));

                    Assert.Equal(WebSocketError.ConnectionClosedPrematurely, newReceiveException.WebSocketErrorCode);

                    Assert.Equal(WebSocketState.Open, clientSocket.State);
                    Assert.Null(clientSocket.CloseStatus);
                }
                else if (PlatformDetection.IsFullFramework)
                {
                    _output.WriteLine("[Windows] ManagedWebSocket-based implementation.");

                    WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync);

                    Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode);

                    WebSocketException newReceiveException =
                        await Assert.ThrowsAsync <WebSocketException>(() => clientSocket.ReceiveAsync(recvSegment, cts.Token));

                    Assert.Equal(WebSocketError.Success, newReceiveException.WebSocketErrorCode);
                    Assert.Equal(
                        ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"),
                        newReceiveException.Message);

                    Assert.Equal(WebSocketState.Aborted, clientSocket.State);
                    Assert.Null(clientSocket.CloseStatus);
                }
                else if (PlatformDetection.IsUap)
                {
                    _output.WriteLine("WinRTWebSocket-based implementation.");

                    const uint WININET_E_CONNECTION_ABORTED = 0x80072EFE;

                    WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync);

                    Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode);
                    Assert.NotNull(pendingReceiveException.InnerException);
                    Assert.Equal(WININET_E_CONNECTION_ABORTED, (uint)pendingReceiveException.InnerException.HResult);

                    WebSocketException newReceiveException =
                        await Assert.ThrowsAsync <WebSocketException>(() => clientSocket.ReceiveAsync(recvSegment, cts.Token));

                    Assert.Equal(WebSocketError.Success, newReceiveException.WebSocketErrorCode);
                    Assert.Equal(
                        ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"),
                        newReceiveException.Message);

                    Assert.Equal(WebSocketState.Aborted, clientSocket.State);
                    Assert.Null(clientSocket.CloseStatus);
                }
                else
                {
                    _output.WriteLine("WinHttpWebSocket-based implementation.");

                    const uint WININET_E_CONNECTION_RESET = 0x80072eff;

                    Win32Exception pendingReceiveException = await Assert.ThrowsAnyAsync <Win32Exception>(() => pendingReceiveAsync);

                    Assert.Equal(WININET_E_CONNECTION_RESET, (uint)pendingReceiveException.HResult);

                    Win32Exception newReceiveException =
                        await Assert.ThrowsAnyAsync <Win32Exception>(() => clientSocket.ReceiveAsync(recvSegment, cts.Token));

                    Assert.Equal(WININET_E_CONNECTION_RESET, (uint)newReceiveException.HResult);

                    Assert.Equal(WebSocketState.Open, clientSocket.State);
                    Assert.Null(clientSocket.CloseStatus);
                }
            };

            await LoopbackServer.CreateServerAsync(async (server, url) =>
            {
                using (ClientWebSocket clientSocket = new ClientWebSocket())
                {
                    await connectToServerThatAbortsConnection(clientSocket, server, url);
                }
            }, options);
        }