We incorrectly assumed that the `payload_length` in the recv start
callback of wslay was the final message size, but according to the
WebSocket protocol, the payload length always refers to the current
frame's payload size.
The protocol, in fact, do not include a "message payload" length on
purpose to allow sending messages of unknown size without forcing the
sender to buffer the whole message (RFC6455 Section 5.4).
This means a receiving peer has no way to know beforehand how long a
message will be, and needs instead to keep track of the length of each
frame until the FIN one is received to properly reconstruct the message
at the end.
This was due by the buffer being cleared on close (including in closing
state) preventing further reads.
This commit changes the close logic to only clear the buffer when the
peer connection has been fully closed (acknowledged by the other end, or
closed due to a "broken" connection).
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.
To avoid this, this commit now ignores the frame recv end callback, and
instead rely on the msg recv callback where we can check the opcode, and
is guaranteed to be called only when the FIN frame is received for text
and binary frames.
Ensure we never read more than we can store during poll.
Raise default max packets to 4096 to maintain the same performance for
the first 2048 packets.
When wslay receives a message that is too big or cause a protocol error,
it automatically sends a close request to the remote peer but it also
completely stop calling the receive callback resulting in the state
being "stuck" as CONNECTED (even if both client and server have
disconnected).
We now check if we sent a close message and reading has been disabled to
manually transition to the "closed" state with the proper reason.
Windows socket implementation is, as usual, broken in many ways.
This includes `setsockopt` failing to set `TCP_NODELAY` if the socket is
still in a connecting state.
This also means we need to keep polling the IP resolver until the socket
reaches the CONNECTED state (so it can set the TCP_NODELAY after the
connection is successful).
Almost all WebSocket implementations (including all major browsers)
disable Nagle's algorithm to favor low latency over packet overhead.
This was also the case in Godot 3.x, while in Godot 4.0 this was only
being done for clients and wasn't even always working due to a bug.
This commit fixes the aforementioned bug, and forces TCP_NODELAY when
accepting a stream as a server.
Random-access access to `List` when iterating is `O(n^2)` (`O(n)` when
accessing a single element)
* Removed subscript operator, in favor of a more explicit `get`
* Added conversion from `Iterator` to `ConstIterator`
* Remade existing operations into other solutions when applicable
The UWP platform port was never ported to the Godot 4.0+ API,
and it's now accumulating bitrot as it doesn't compile, and thus
we no longer propagate platform changes in it.
So we finally remove to acknowledge this state. There's still some
interest in reviving the UWP port eventually, especially as support
for Direct3D 12 will soon be merged, but when that happens it will
be easiest to redo it from scratch.
We don't use that info for anything, and it generates unnecessary diffs
every time we bump the minor version (and CI failures if we forget to
sync some files from opt-in modules (mono, text_server_fb).
This applies our existing style guide, and adds a new rule to that style
guide for modular components such as platform ports and modules:
Includes from the platform port or module ("local" includes) should be listed
first in their own block using relative paths, before Godot's "core" includes
which use "absolute" (project folder relative) paths, and finally thirdparty
includes.
Includes in `#ifdef`s come after their relevant section, i.e. the overall
structure is:
- Local includes
* Conditional local includes
- Core includes
* Conditional core includes
- Thirdparty includes
* Conditional thirdparty includes
If no StreamPeerTLS implementation is available, HTTPClient and
WebSocketPeer will now correctly refuse to connect using TLS returning
ERR_UNAVAILABLE.
Similarly, ENetConnection will refuse to setup DTLS when PacketPeerDTLS
is not available.
Adds a check to make_rst to look for matches
between the text inside of the [code][/code] tag
and known param identifiers.
Fixes most of what was revealed.