dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.47k stars 4.77k forks source link

ClientWebSocket aborts on closes when going thru a proxy #25440

Open davidsh opened 6 years ago

davidsh commented 6 years ago

While working on dotnet/runtime#24965, I noticed that the following test will fail. There seems to be a problem with the close frame exchange and final TCP socket close when going thru a proxy.

Repro test (not yet in repo):

[OuterLoop] // TODO: Issue dotnet/runtime#18406
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task Proxy_ConnectThruProxy_Success(Uri server)
{
    IWebProxy proxy = new WebProxy(new Uri("http://localhost:8080/"));
    using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(
        server,
        TimeOutMilliseconds,
        _output,
        default(TimeSpan),
        proxy))
    {
        var cts = new CancellationTokenSource(TimeOutMilliseconds);
        Assert.Equal(WebSocketState.Open, cws.State);

        var closeStatus = WebSocketCloseStatus.NormalClosure;
        string closeDescription = "Normal Closure";

        await cws.CloseAsync(closeStatus, closeDescription, cts.Token);

        // Verify a clean close frame handshake.
        Assert.Equal(WebSocketState.Closed, cws.State); // *** FAILS HERE ***
        Assert.Equal(closeStatus, cws.CloseStatus);
        Assert.Equal(closeDescription, cws.CloseStatusDescription);
    }
}

Fails with error:

    System.Net.WebSockets.Client.Tests.ClientWebSocketOptionsTests.Proxy_SecureConnectThruProxy_Success(server: ws://corefx-net.cloudapp.net/WebSocket/EchoWeb
  Socket.ashx) [FAIL]
        Assert.Equal() Failure
        Expected: Closed
        Actual:   Aborted
        Stack Trace:
           s:\GitHub\corefx\src\System.Net.WebSockets.Client\tests\ClientWebSocketOptionsTests.cs(90,0): at System.Net.WebSockets.Client.Tests.ClientWebSocketO
  ptionsTests.Proxy_SecureConnectThruProxy_Success(Uri server)
           --- End of stack trace from previous location where exception was thrown ---
     System.Net.WebSockets.Client.Tests.ClientWebSocketOptionsTests.Proxy_SecureConnectThruProxy_Success(server: wss://corefx-net.cloudapp.net/WebSocket/EchoWe
  bSocket.ashx) [FAIL]
        Assert.Equal() Failure
        Expected: Closed
        Actual:   Aborted
        Stack Trace:
           s:\GitHub\corefx\src\System.Net.WebSockets.Client\tests\ClientWebSocketOptionsTests.cs(90,0): at System.Net.WebSockets.Client.Tests.ClientWebSocketO
  ptionsTests.Proxy_SecureConnectThruProxy_Success(Uri server)
           --- End of stack trace from previous location where exception was thrown ---
davidsh commented 6 years ago

cc: @dotnet/ncl

davidsh commented 6 years ago

It seems that the behavior differs depending on which proxy is used. Using the test 'HappySockets' proxy server, we get a RST back after the close frame (which causes this test failure). Using Fiddler, we get a FIN.

However, the test passes using .NET Framework and 'HappySockets' proxy server.

Need to investigate further to determine whether or not this is a test bug (proxy server shouldn't be sending back RST) or a difference between .NET Core and .NET Framework.

stephentoub commented 4 years ago

@davidsh, there's still a test disabled against this issue: https://github.com/dotnet/runtime/blob/ccf6aedb63c37ea8e10e4f5b5d9d23a69bdd9489/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketOptionsTests.cs#L65-L68

dotnet-policy-service[bot] commented 1 week ago

Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

This process is part of our issue cleanup automation.