mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 21:27:34 +00:00
SpiceAgent: Add support for reading chunks larger than 2048 bytes
This commit is contained in:
parent
3b6d63f723
commit
50a8db3922
3 changed files with 69 additions and 24 deletions
44
Userland/Services/SpiceAgent/ChunkHeader.h
Normal file
44
Userland/Services/SpiceAgent/ChunkHeader.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Caoimhe Byrne <caoimhebyrne06@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Forward.h>
|
||||||
|
#include <AK/Traits.h>
|
||||||
|
#include <AK/Types.h>
|
||||||
|
|
||||||
|
namespace SpiceAgent {
|
||||||
|
|
||||||
|
class [[gnu::packed]] ChunkHeader {
|
||||||
|
public:
|
||||||
|
// Indicates where the message has come from
|
||||||
|
enum class Port : u32 {
|
||||||
|
Client = 1,
|
||||||
|
|
||||||
|
// There are currently no messages which are meant for the server, so all messages sent by the agent (us) with this port are discarded.
|
||||||
|
Server
|
||||||
|
};
|
||||||
|
|
||||||
|
ChunkHeader(Port port, u32 size)
|
||||||
|
: m_port(port)
|
||||||
|
, m_size(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Port port() const { return m_port; }
|
||||||
|
u32 size() const { return m_size; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Port m_port { Port::Client };
|
||||||
|
u32 m_size { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AK::Traits<SpiceAgent::ChunkHeader> : public AK::GenericTraits<SpiceAgent::ChunkHeader> {
|
||||||
|
static constexpr bool is_trivially_serializable() { return true; }
|
||||||
|
};
|
|
@ -120,15 +120,19 @@ ErrorOr<void> SpiceAgent::did_receive_clipboard_message(ClipboardMessage& messag
|
||||||
|
|
||||||
ErrorOr<ByteBuffer> SpiceAgent::read_message_buffer()
|
ErrorOr<ByteBuffer> SpiceAgent::read_message_buffer()
|
||||||
{
|
{
|
||||||
auto port = TRY(m_spice_device->read_value<Port>());
|
auto header = TRY(m_spice_device->read_value<ChunkHeader>());
|
||||||
if (port != Port::Client) {
|
auto buffer = TRY(ByteBuffer::create_uninitialized(header.size()));
|
||||||
return Error::from_string_literal("Attempted to read message bytes from a port that wasn't meant for the client!");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto size = TRY(m_spice_device->read_value<u32>());
|
|
||||||
auto buffer = TRY(ByteBuffer::create_uninitialized(size));
|
|
||||||
TRY(m_spice_device->read_until_filled(buffer));
|
TRY(m_spice_device->read_until_filled(buffer));
|
||||||
|
|
||||||
|
// If the header's size is bigger than or equal to 2048, we may have more data incoming.
|
||||||
|
while (header.size() >= message_buffer_threshold) {
|
||||||
|
header = TRY(m_spice_device->read_value<ChunkHeader>());
|
||||||
|
|
||||||
|
auto new_buffer = TRY(ByteBuffer::create_uninitialized(header.size()));
|
||||||
|
TRY(m_spice_device->read_until_filled(new_buffer));
|
||||||
|
TRY(buffer.try_append(new_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ChunkHeader.h"
|
||||||
#include "Message.h"
|
#include "Message.h"
|
||||||
#include "MessageHeader.h"
|
#include "MessageHeader.h"
|
||||||
#include <AK/MemoryStream.h>
|
#include <AK/MemoryStream.h>
|
||||||
|
@ -16,16 +17,12 @@
|
||||||
|
|
||||||
namespace SpiceAgent {
|
namespace SpiceAgent {
|
||||||
|
|
||||||
|
// The maximum amount of data that can be contained within a message's buffer.
|
||||||
|
// If the buffer's length is equal to this, then the next data recieved will be more data from the same buffer.
|
||||||
|
constexpr u32 message_buffer_threshold = 2048;
|
||||||
|
|
||||||
class SpiceAgent {
|
class SpiceAgent {
|
||||||
public:
|
public:
|
||||||
// Indicates where the message has come from.
|
|
||||||
enum class Port : u32 {
|
|
||||||
Client = 1,
|
|
||||||
|
|
||||||
// There are currently no messages which are meant for the server, so all messages sent by the agent (us) with this port are discarded.
|
|
||||||
Server
|
|
||||||
};
|
|
||||||
|
|
||||||
static ErrorOr<NonnullOwnPtr<SpiceAgent>> create(StringView device_path);
|
static ErrorOr<NonnullOwnPtr<SpiceAgent>> create(StringView device_path);
|
||||||
SpiceAgent(NonnullOwnPtr<Core::File> spice_device, Vector<Capability> const& capabilities);
|
SpiceAgent(NonnullOwnPtr<Core::File> spice_device, Vector<Capability> const& capabilities);
|
||||||
|
|
||||||
|
@ -39,20 +36,20 @@ public:
|
||||||
TRY(message.write_to_stream(message_stream));
|
TRY(message.write_to_stream(message_stream));
|
||||||
|
|
||||||
// Create a header to be sent.
|
// Create a header to be sent.
|
||||||
auto header_stream = AK::AllocatingMemoryStream();
|
auto message_header_stream = AK::AllocatingMemoryStream();
|
||||||
auto header = MessageHeader(message.type(), message_stream.used_buffer_size());
|
auto message_header = MessageHeader(message.type(), message_stream.used_buffer_size());
|
||||||
TRY(header_stream.write_value(header));
|
TRY(message_header_stream.write_value(message_header));
|
||||||
|
|
||||||
|
// The length given in the chunk header is the length of the message header, and the message combined
|
||||||
|
auto length = message_header_stream.used_buffer_size() + message_stream.used_buffer_size();
|
||||||
|
|
||||||
// Currently, there are no messages from the agent which are meant for the server.
|
// Currently, there are no messages from the agent which are meant for the server.
|
||||||
// So, all messages sent by the agent with a port of Port::Server get dropped silently.
|
// So, all messages sent by the agent with a port of Port::Server get dropped silently.
|
||||||
TRY(m_spice_device->write_value(Port::Client));
|
auto chunk_header = ChunkHeader(ChunkHeader::Port::Client, length);
|
||||||
|
TRY(m_spice_device->write_value(chunk_header));
|
||||||
// The length of the subsequent data.
|
|
||||||
auto length = header_stream.used_buffer_size() + message_stream.used_buffer_size();
|
|
||||||
TRY(m_spice_device->write_value<u32>(length));
|
|
||||||
|
|
||||||
// The message's header.
|
// The message's header.
|
||||||
TRY(m_spice_device->write_until_depleted(TRY(header_stream.read_until_eof())));
|
TRY(m_spice_device->write_until_depleted(TRY(message_header_stream.read_until_eof())));
|
||||||
|
|
||||||
// The message content.
|
// The message content.
|
||||||
TRY(m_spice_device->write_until_depleted(TRY(message_stream.read_until_eof())));
|
TRY(m_spice_device->write_until_depleted(TRY(message_stream.read_until_eof())));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue