Repository: godotengine/godot (language: cpp)

Issue:
Websocket client cuts message after 2^15 bytes
### Tested versions

- v4.3.stable.official [77dcf97d8]: **ok**
- v4.4.dev1.official [28a72fa43]: **ok**
- v4.4.dev2.official [97ef3c837]: **ok**
- v4.4.dev3.official [f4af8201b]: **ok**
- v4.4.dev4.official [36e6207bb]: **ok**
- v4.4.dev5.official [9e6098432]: **fails**
- v4.4.dev6.official [1f47e4c4e]: **fails**
- v4.4.dev7.official [46c8f8c5c]: **fails**
- v4.4.beta1.official [d33da79d3]: **fails**

### System information

Godot v4.4.beta1 - Windows 11 (build 26100) - Multi-window, 2 monitors - OpenGL 3 (Compatibility) - NVIDIA GeForce GTX 1080 Ti (NVIDIA; 32.0.15.6614) - AMD Ryzen 9 7900X 12-Core Processor (24 threads)

### Issue description

The Godot Websocket client cuts received messages after 2^15 bytes.

This is a regression since `v4.4.dev5`.

### Steps to reproduce

I could **NOT** reproduce the issue with Godot's builtin websocket server (also included in MRP). I provide another websocket server based on Go.
You can either use the devcontainer and run  `Launch server` or run `cd server && go run main.go` in the terminal. If not using a devcontainer do `cd server && go mod download && go run main.go` (i can also provide binaries if wished)
The server listens on port `9080` and answers `ping` with `pong` and any other message should be a number, which will then send a message with that many `G`s back.
In Godot just hit run, what messages are sent or received are logged to the output.

### Minimal reproduction project (MRP)

[godot-ws.zip](https://github.com/user-attachments/files/18470551/godot-ws.zip)
Reimplement _wsl_frame_recv_end_callback()
Fix #101811

An [extraneous call to clear the PendingMessage](https://github.com/godotengine/godot/pull/98343/files#diff-9348306b0794d0739d7d81022e096cede90d18fe9b9113f60c36e802ce572634R621) was in the original PR #98343, which was moved to `_wsl_send_callback()` in #100631 in an attempt to fix incoming control frames during a multi-frame message.

This PR seeks to restore the fixed multi-frame logic to `_wsl_frame_recv_end_callback()` while limiting that callback to text and binary frames only, as originally intended.


Discussion / hints:
Confirmed reproducible on macOS 15.2 running on an M2 Air with b0655dc86f, the most recent commit on `master` at the time of my comment.

The built-in WebSocket server works fine, but the external server included with this issue does not.
As stated in https://github.com/godotengine/godot/pull/100631 :

The wslay library, somehow unintuitively, will call the frame recv end
callback for control frames.

This has the side effect that while receiving a long message (i.e. a
multi-frame message), if a control frame (e.g. a ping or pong) is received
it may seem that a FIN frame has been received, resulting in the current
code truncating the message.

The library do not provide a way  to check the opcode in the callback (you
are reading the opcode from the value we store, which is always going to be
either a binary or text frame because we only store those).

So this is the same as doing no check at all, like we did before #100631 .

I'm currently traveling, I'll try the MRP as soon as I can to see why
#100631 doesn't appear to be working for you.

On Sat, Jan 25, 2025, 21:38 Lily ***@***.***> wrote:

> @gofastlily <https://github.com/gofastlily> requested review from
> @godotengine/network on: #102038
> <https://github.com/godotengine/godot/pull/102038> Reimplement
> _wsl_frame_recv_end_callback() as a code owner.
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/godotengine/godot/pull/102038#event-16068207083>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAM4C3W6ZHVV5K54HMKPO2L2MPY6DAVCNFSM6AAAAABV3V2OOSVHI2DSMVQWIX3LMV45UABCJFZXG5LFIV3GK3TUJZXXI2LGNFRWC5DJN5XDWMJWGA3DQMRQG4YDQMY>
> .
> You are receiving this because your review was requested.Message ID:
> ***@***.***>
>

Thanks for taking a look.  I'll do some digging too and try to fix my understanding of the situation.

Fix patch:
diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp
index f50b4c480652..1a1f52a8a06b 100644
--- a/modules/websocket/wsl_peer.cpp
+++ b/modules/websocket/wsl_peer.cpp
@@ -598,7 +598,6 @@ void WSLPeer::_wsl_recv_start_callback(wslay_event_context_ptr ctx, const struct
 		// Get ready to process a data package.
 		PendingMessage &pm = peer->pending_message;
 		pm.opcode = op;
-		pm.payload_size = arg->payload_length;
 	}
 }
 
@@ -608,6 +607,7 @@ void WSLPeer::_wsl_frame_recv_chunk_callback(wslay_event_context_ptr ctx, const
 	if (pm.opcode != 0) {
 		// Only write the payload.
 		peer->in_buffer.write_packet(arg->data, arg->data_length, nullptr);
+		pm.payload_size += arg->data_length;
 	}
 }
 


Test patch: