Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Fix ClientWebSocket close handshake when using proxy #36928

Merged
merged 2 commits into from
Apr 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/Common/src/System/Net/WebSockets/ManagedWebSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,11 @@ private async Task HandleReceivedCloseAsync(MessageHeader header, CancellationTo
lock (StateUpdateLock)
{
_receivedCloseFrame = true;
if (_state < WebSocketState.CloseReceived)
if (_sentCloseFrame && _state < WebSocketState.Closed)
{
_state = WebSocketState.Closed;
}
else if (_state < WebSocketState.CloseReceived)
{
_state = WebSocketState.CloseReceived;
}
Expand Down Expand Up @@ -1153,7 +1157,11 @@ private async Task SendCloseFrameAsync(WebSocketCloseStatus closeStatus, string
lock (StateUpdateLock)
{
_sentCloseFrame = true;
if (_state <= WebSocketState.CloseReceived)
if (_receivedCloseFrame && _state < WebSocketState.Closed)
{
_state = WebSocketState.Closed;
}
else if (_state < WebSocketState.CloseSent)
{
_state = WebSocketState.CloseSent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using System.Threading;
using System.Threading.Tasks;

namespace System.Net.Http.Functional.Tests
namespace System.Net.Test.Common
{
/// <summary>
/// Provides a test-only HTTP proxy. Handles multiple connections/requests and CONNECT tunneling for HTTPS
Expand Down Expand Up @@ -210,7 +210,7 @@ private async Task ProcessConnectMethod(NetworkStream clientStream, string remot
{
byte[] buffer = new byte[8000];
int bytesRead;
while ((bytesRead = await clientStream.ReadAsync(buffer)) > 0)
while ((bytesRead = await clientStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await serverStream.WriteAsync(buffer, 0, bytesRead);
}
Expand All @@ -228,7 +228,7 @@ private async Task ProcessConnectMethod(NetworkStream clientStream, string remot
{
byte[] buffer = new byte[8000];
int bytesRead;
while ((bytesRead = await serverStream.ReadAsync(buffer)) > 0)
while ((bytesRead = await serverStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await clientStream.WriteAsync(buffer, 0, bytesRead);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
<Compile Include="$(CommonTestPath)\System\Net\VerboseTestLogging.cs">
<Link>Common\System\Net\VerboseTestLogging.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Net\Http\LoopbackProxyServer.cs">
<Link>Common\System\Net\Http\LoopbackProxyServer.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Net\Http\LoopbackServer.cs">
<Link>Common\System\Net\Http\LoopbackServer.cs</Link>
</Compile>
Expand Down Expand Up @@ -120,7 +123,6 @@
<Compile Include="HttpProtocolTests.cs" />
<Compile Include="HttpRequestMessageTest.cs" />
<Compile Include="HttpResponseMessageTest.cs" />
<Compile Include="LoopbackProxyServer.cs" />
<Compile Include="MessageProcessingHandlerTest.cs" />
<Compile Include="MultipartContentTest.cs" />
<Compile Include="MultipartFormDataContentTest.cs" />
Expand Down
36 changes: 28 additions & 8 deletions src/System.Net.WebSockets.Client/tests/ConnectTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class ConnectTest : ClientWebSocketTestBase
{
public ConnectTest(ITestOutputHelper output) : base(output) { }

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(UnavailableWebSocketServers))]
public async Task ConnectAsync_NotWebSocketServer_ThrowsWebSocketExceptionWithMessage(Uri server, string exceptionMessage, WebSocketError errorCode)
{
Expand All @@ -40,21 +40,21 @@ public async Task ConnectAsync_NotWebSocketServer_ThrowsWebSocketExceptionWithMe
}
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task EchoBinaryMessage_Success(Uri server)
{
await WebSocketHelper.TestEcho(server, WebSocketMessageType.Binary, TimeOutMilliseconds, _output);
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task EchoTextMessage_Success(Uri server)
{
await WebSocketHelper.TestEcho(server, WebSocketMessageType.Text, TimeOutMilliseconds, _output);
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoHeadersServers))]
public async Task ConnectAsync_AddCustomHeaders_Success(Uri server)
{
Expand Down Expand Up @@ -92,7 +92,7 @@ public async Task ConnectAsync_AddCustomHeaders_Success(Uri server)
}

[ActiveIssue(18784, TargetFrameworkMonikers.NetFramework)]
[OuterLoop]
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported))]
public async Task ConnectAsync_AddHostHeader_Success()
{
Expand Down Expand Up @@ -136,7 +136,7 @@ public async Task ConnectAsync_AddHostHeader_Success()
}
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoHeadersServers))]
public async Task ConnectAsync_CookieHeaders_Success(Uri server)
{
Expand Down Expand Up @@ -185,7 +185,7 @@ public async Task ConnectAsync_CookieHeaders_Success(Uri server)
}
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task ConnectAsync_PassNoSubProtocol_ServerRequires_ThrowsWebSocketException(Uri server)
{
Expand All @@ -210,7 +210,7 @@ public async Task ConnectAsync_PassNoSubProtocol_ServerRequires_ThrowsWebSocketE
}
}

[OuterLoop] // TODO: Issue #11345
[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task ConnectAsync_PassMultipleSubProtocols_ServerRequires_ConnectionUsesAgreedSubProtocol(Uri server)
{
Expand Down Expand Up @@ -248,5 +248,25 @@ await LoopbackServer.CreateClientAndServerAsync(async uri =>
Assert.True(await LoopbackHelper.WebSocketHandshakeAsync(connection));
}), new LoopbackServer.Options { WebSocketEndpoint = true });
}

[OuterLoop("Uses external servers")]
[ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
public async Task ConnectAndCloseAsync_UseProxyServer_ExpectedClosedState(Uri server)
{
using (var cws = new ClientWebSocket())
using (var cts = new CancellationTokenSource(TimeOutMilliseconds))
using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
{
cws.Options.Proxy = new WebProxy(proxyServer.Uri);
await cws.ConnectAsync(server, cts.Token);

string expectedCloseStatusDescription = "Client close status";
await cws.CloseAsync(WebSocketCloseStatus.NormalClosure, expectedCloseStatusDescription, cts.Token);

Assert.Equal(WebSocketState.Closed, cws.State);
Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus);
Assert.Equal(expectedCloseStatusDescription, cws.CloseStatusDescription);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<Compile Include="$(CommonTestPath)\System\Net\Configuration.WebSockets.cs">
<Link>Common\System\Net\Configuration.WebSockets.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Net\Http\LoopbackProxyServer.cs">
<Link>Common\System\Net\Http\LoopbackProxyServer.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Net\Http\LoopbackServer.cs">
<Link>Common\System\Net\Http\LoopbackServer.cs</Link>
</Compile>
Expand Down