LibRequests+RequestServer: Send oversized ws frames via shared memory

This commit is contained in:
Ali Mohammad Pur 2026-05-14 14:39:07 +02:00 committed by Ali Mohammad Pur
parent 842e8a6796
commit 7c4ecaf509
4 changed files with 28 additions and 0 deletions

View file

@ -4,11 +4,14 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibCore/AnonymousBuffer.h>
#include <LibRequests/RequestClient.h> #include <LibRequests/RequestClient.h>
#include <LibRequests/WebSocket.h> #include <LibRequests/WebSocket.h>
namespace Requests { namespace Requests {
static constexpr size_t WEBSOCKET_SHARED_MEMORY_THRESHOLD = 16 * MiB;
WebSocket::WebSocket(RequestClient& client, u64 websocket_id) WebSocket::WebSocket(RequestClient& client, u64 websocket_id)
: m_client(client) : m_client(client)
, m_websocket_id(websocket_id) , m_websocket_id(websocket_id)
@ -39,6 +42,16 @@ void WebSocket::send(ReadonlyBytes binary_or_text_message, bool is_text)
{ {
if (!m_client) if (!m_client)
return; return;
if (binary_or_text_message.size() >= WEBSOCKET_SHARED_MEMORY_THRESHOLD) {
auto buffer_or_error = Core::AnonymousBuffer::create_with_size(binary_or_text_message.size());
if (!buffer_or_error.is_error()) {
auto buffer = buffer_or_error.release_value();
__builtin_memcpy(buffer.data<void>(), binary_or_text_message.data(), binary_or_text_message.size());
m_client->async_websocket_send_shared(m_websocket_id, is_text, move(buffer));
return;
}
dbgln("WebSocket::send: failed to allocate shared buffer for {} bytes: {}", binary_or_text_message.size(), buffer_or_error.error());
}
m_client->async_websocket_send(m_websocket_id, is_text, binary_or_text_message); m_client->async_websocket_send(m_websocket_id, is_text, binary_or_text_message);
} }

View file

@ -586,6 +586,19 @@ void ConnectionFromClient::websocket_send(u64 websocket_id, bool is_text, ByteBu
connection->send(WebSocket::Message { move(data), is_text }); connection->send(WebSocket::Message { move(data), is_text });
} }
void ConnectionFromClient::websocket_send_shared(u64 websocket_id, bool is_text, Core::AnonymousBuffer data)
{
auto* connection = m_websockets.get(websocket_id).value_or({});
if (!connection || connection->ready_state() != WebSocket::ReadyState::Open)
return;
auto byte_buffer_or_error = ByteBuffer::copy(data.bytes());
if (byte_buffer_or_error.is_error()) {
dbgln("websocket_send_shared: failed to copy {} bytes from shared buffer: {}", data.size(), byte_buffer_or_error.error());
return;
}
connection->send(WebSocket::Message { byte_buffer_or_error.release_value(), is_text });
}
void ConnectionFromClient::websocket_close(u64 websocket_id, u16 code, ByteString reason) void ConnectionFromClient::websocket_close(u64 websocket_id, u16 code, ByteString reason)
{ {
if (m_pending_websockets.remove(websocket_id)) { if (m_pending_websockets.remove(websocket_id)) {

View file

@ -72,6 +72,7 @@ private:
virtual void websocket_connect(u64 websocket_id, URL::URL, ByteString, Vector<ByteString>, Vector<ByteString>, Vector<HTTP::Header>) override; virtual void websocket_connect(u64 websocket_id, URL::URL, ByteString, Vector<ByteString>, Vector<ByteString>, Vector<HTTP::Header>) override;
virtual void websocket_send(u64 websocket_id, bool, ByteBuffer) override; virtual void websocket_send(u64 websocket_id, bool, ByteBuffer) override;
virtual void websocket_send_shared(u64 websocket_id, bool, Core::AnonymousBuffer) override;
virtual void websocket_close(u64 websocket_id, u16, ByteString) override; virtual void websocket_close(u64 websocket_id, u16, ByteString) override;
virtual Messages::RequestServer::WebsocketSetCertificateResponse websocket_set_certificate(u64, ByteString, ByteString) override; virtual Messages::RequestServer::WebsocketSetCertificateResponse websocket_set_certificate(u64, ByteString, ByteString) override;

View file

@ -42,6 +42,7 @@ endpoint RequestServer
// Websocket Connection API // Websocket Connection API
websocket_connect(u64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, Vector<HTTP::Header> additional_request_headers) =| websocket_connect(u64 websocket_id, URL::URL url, ByteString origin, Vector<ByteString> protocols, Vector<ByteString> extensions, Vector<HTTP::Header> additional_request_headers) =|
websocket_send(u64 websocket_id, bool is_text, ByteBuffer data) =| websocket_send(u64 websocket_id, bool is_text, ByteBuffer data) =|
websocket_send_shared(u64 websocket_id, bool is_text, Core::AnonymousBuffer data) =|
websocket_close(u64 websocket_id, u16 code, ByteString reason) =| websocket_close(u64 websocket_id, u16 code, ByteString reason) =|
websocket_set_certificate(u64 request_id, ByteString certificate, ByteString key) => (bool success) websocket_set_certificate(u64 request_id, ByteString certificate, ByteString key) => (bool success)