Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow nonstandard close statuses in ManagedWebSocket #83713

Closed
wants to merge 1 commit into from

Conversation

IDisposable
Copy link
Contributor

@IDisposable IDisposable commented Mar 21, 2023

Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of WebSocketCloseStatus values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description by adding them to the private IsValueCloseStatus method switch statement declaring them as valid true.

Fixes Issue #82602

Description

The current implementation of ManagedWebSocket explicitly declares some WebSocketCloseStatus values as "acceptable" reasons to close the socket. For those, the information status description is extracted and made available. For all other values, the close status is rejected and the closing information is discarded.

This means that things like BadGateway (1014), or ServiceRestart (1012), or TryAgainLater (1013) will be declared invalid by ManagedWebSocket.IsValidCloseStatus and thus not handled cleanly even though they could happen after a web socket is completely setup. These codes are documented here as valid server-initiated close reasons.

Customer Impact

Lost information and ragged closing of a web socket when a server-side or proxy closes because of any of the previously rejected values:

  • ServiceRestart = 1012 // indicates that the server / service is restarting.
  • TryAgainLater = 1013 // indicates that a temporary server condition forced blocking the client's request.
  • BadGateway = 1014 // indicates that the server acting as gateway received an invalid response

This codes are documented here and here as IANA registered and in the Mozilla docs

Regression

No

Testing

Added test cases for all three to new WebSocketCloseTests.cs file with no regressions in current tests.

Risk

This does not change the public enum of WebSocketCloseStatus as we don't want to invoke public review and the values are not mentioned in the RFC.

Package authoring signed off?

N/A

Add ServiceRestart (1012), TryAgainLater (1013), and
BadGateway (1014) to the list of `WebSocketCloseStatus`
values and allow them to be used as valid WebSocket
close statuses so we don't reject the close and discard
the status description.
Fixes dotnet#82602
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Mar 21, 2023
@ghost
Copy link

ghost commented Mar 21, 2023

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Add ServiceRestart (1012), TryAgainLater (1013), and BadGateway (1014) to the list of WebSocketCloseStatus values and allow them to be used as valid WebSocket close statuses so we don't reject the close and discard the status description by adding them to the private IsValueCloseStatus method switch statement declaring them as valid true.

Fixes Issue #82602

Description

The current implementation of ManagedWebSocket explicitly declares some WebSocketCloseStatus values as "acceptable" reasons to close the socket. For those, the information status decsription is extracted and made available. For all other values, the close status is rejected and the closing information is discarded.

This means that things like BadGateway (1014), or ServiceRestart (1012), or TryAgainLater (1013) will be declared invalid by ManagedWebSocket.IsValidCloseStatus and thus not handled cleanly even though they could happen after a web socket is completely setup.

Customer Impact

Lost information and ragged closing of a web socket when a server-side or proxy closes because of any of the previously rejected values:

  • ServiceRestart = 1012 // indicates that the server / service is restarting.
  • TryAgainLater = 1013 // indicates that a temporary server condition forced blocking the client's request.
  • BadGateway = 1014 // indicates that the server acting as gateway received an invalid response

Regression

No

Testing

Added test cases for all three to the HttpListenerWebSocketTests.cs file with no regressions found.

Risk

Changes the public exposed enum of WebSocketCloseStatus.cs adding three new values that were previously not documented.

Package authoring signed off?

IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary package authoring and gotten it explicitly reviewed.

Author: IDisposable
Assignees: -
Labels:

area-System.Net, community-contribution

Milestone: -

@CarnaViire
Copy link
Member

Thank you for your contribution @IDisposable!

However, you cannot add public API without going through the API review process first.

I strongly believe the issue can be fixed without adding new enum values, just by casting ints to WebSocketCloseStatus in the checks and tests. Please let me know what kinds of problems you are experiencing with this -- I would be happy to help.

Also, when adding the tests, could you please add them to the library that you were changing, i.e. System.Net.WebSockets, not to HttpListener?
You can test receiving the close status by supplying a MemoryStream with the close frame bits written into it, in the same way this test is constructed:

public async Task ReceiveAsync_InvalidPayloadLength_AbortsAndThrowsException(byte[] lenBytes, bool shouldFail)
{
var frame = new byte[11];
frame[0] = 0b1_000_0010; // FIN, RSV, OPCODE
frame[1] = 0b0_1111111; // MASK, PAYLOAD_LEN
Assert.Equal(8, lenBytes.Length);
Array.Copy(lenBytes, 0, frame, 2, lenBytes.Length); // EXTENDED_PAYLOAD_LEN
frame[10] = (byte)'a';

@IDisposable
Copy link
Contributor Author

IDisposable commented Mar 21, 2023

Reworking this to not use public API changes... PR will follow in 12 36 hours or so

@IDisposable IDisposable changed the title Add additional close statuses in ManagedWebSocket Allow nonstandard close statuses in ManagedWebSocket Mar 23, 2023
@IDisposable
Copy link
Contributor Author

Replaced by #83827

@IDisposable IDisposable deleted the add-websocket-closes branch March 23, 2023 16:46
@IDisposable
Copy link
Contributor Author

@CarnaViire I reimplemented this PR without changing the public enum.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 22, 2023
@karelz karelz added this to the 8.0.0 milestone May 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants