LibGUI/WindowServer: Rework packet serialization

Instead of sending while serializing (what even was that), we serialize
the whole packet into a buffer which can be sent in one go. First of all
this reduces the number of sends by a lot. This also fixes WindowServer
ending up sending partial packets when client is not responsive.
Previously we would just try sending once, if any send failed the send
was aborted while partial packet was already transmitted. This lead to
packet stream being out of sync leading to the client killing itself.
Now we allow 64 KiB outgoing buffer per client. If this buffer ever fills
up, we will not send partial packets.
This commit is contained in:
2026-04-07 09:13:34 +03:00
parent 2f9b8b6fc9
commit a4ba1da65a
7 changed files with 373 additions and 292 deletions

View File

@@ -20,8 +20,10 @@ class WindowServer
public:
struct ClientData
{
size_t packet_buffer_nread = 0;
BAN::Vector<uint8_t> packet_buffer;
size_t in_buffer_size { 0 };
BAN::Array<uint8_t, 64 * 1024> in_buffer;
size_t out_buffer_size { 0 };
BAN::Array<uint8_t, 64 * 1024> out_buffer;
};
public:
@@ -54,7 +56,7 @@ public:
Rectangle cursor_area() const;
Rectangle resize_area(Position cursor) const;
void add_client_fd(int fd);
BAN::ErrorOr<void> add_client_fd(int fd);
void remove_client_fd(int fd);
ClientData& get_client_data(int fd);
@@ -65,11 +67,14 @@ private:
void mark_pending_sync(Rectangle area);
bool resize_window(BAN::RefPtr<Window> window, uint32_t width, uint32_t height) const;
bool resize_window(BAN::RefPtr<Window> window, uint32_t width, uint32_t height);
BAN::RefPtr<Window> find_window_with_fd(int fd) const;
BAN::RefPtr<Window> find_hovered_window() const;
template<typename T>
BAN::ErrorOr<void> append_serialized_packet(const T& packet, int fd);
private:
struct RangeList
{