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