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

Connection closed when sending more than 126 bytes in a given message via WebSocket #138

Open
KieranDevvs opened this issue Feb 6, 2022 · 3 comments

Comments

@KieranDevvs
Copy link

KieranDevvs commented Feb 6, 2022

When sending a message of 126 bytes or more to System.Net.WebSockets.ClientWebSocket, the connection forcibly closes.
Any messages with 125 bytes or less are received as expected.

I have tested System.Net.WebSockets.ClientWebSocket under a Blazor WASM client environment (using the browser API) and also from a console app, both tests fail. However, other websocket client implementations such as WebSocket4Net work with Bedrock being the server. I have also tested System.Net.WebSockets.ClientWebSocket with another WebSocket server and it appears to work as intended which indicates there is some compatibility issues with Bedrock WebSockets.

Unhandled exception rendering component: The WebSocket is in an invalid state ('Closed') for this operation. Valid states are: 'Open, CloseSent'
System.Net.WebSockets.WebSocketException (0x80004005): The WebSocket is in an invalid state ('Closed') for this operation. Valid states are: 'Open, CloseSent'
   at System.Net.WebSockets.BrowserWebSocket.ReceiveAsync(ArraySegment`1 buffer, CancellationToken cancellationToken)
   at ClientConnection.ListenAsync(CancellationToken cancellationToken) in BedrockWebSocketTest.Client\ClientConnection.cs:line 28
   at BedrockWebSocketTest.Client.Pages.Index.Start() in BedrockWebSocketTest.Client\Pages\Index.razor:line 16
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

Here is a project solution to reproduce the issue: https://github.com/KieranDevvs/BedrockWebSocketTest

Run both projects, and hit start within the index page of the Blazor WASM web app. You should see the connection drop.
Now go into SessionHandler.cs within the server project and change Enumerable.Range(0, 15).Select(x => "really")
to Enumerable.Range(0, 14).Select(x => "really") to lower the message size from 128 to 121. When you run the test this time, the message is received within the client and is printed to the console.

@KieranDevvs
Copy link
Author

Had some time tonight to dig a little deeper, it appears the client is failing when its attempting to validate the header payload is UFT8.
image

image

image

@KieranDevvs
Copy link
Author

KieranDevvs commented Feb 13, 2022

Tested the same client out with the following server with success:

public class ConsoleServer
    {
        static HttpListener httpListener = new HttpListener();
        private static Mutex signal = new Mutex();
        public static async Task Main(string[] args)
        {
            httpListener.Prefixes.Add("http://localhost:1337/");
            httpListener.Start();
            Console.WriteLine("Accepting connections");
            while (signal.WaitOne())
            {
                ReceiveConnection();
            }

        }

        public static async Task ReceiveConnection()
        {
            HttpListenerContext context = await
            httpListener.GetContextAsync();
            if (context.Request.IsWebSocketRequest)
            {
                HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null);
                WebSocket webSocket = webSocketContext.WebSocket;
                if (webSocket.State == WebSocketState.Open)
                {
                    var payload = Encoding.UTF8.GetBytes($"This is a {string.Join(" ", Enumerable.Range(0, 20).Select(x => "really"))} long message.");
                    await webSocket.SendAsync(payload, WebSocketMessageType.Binary, true, CancellationToken.None);
                }
            }
            signal.ReleaseMutex();
        }
    }

@davidfowl
Copy link
Owner

Thanks for the repro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants