2021-07-12 17:25:37 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021, Kyle Pereira <kyle@xylepereira.me>
|
2023-05-13 15:08:23 +03:00
|
|
|
* Copyright (c) 2023, Caoimhe Byrne <caoimhebyrne06@gmail.com>
|
2021-07-12 17:25:37 +03:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
2022-09-18 02:14:45 +03:00
|
|
|
#pragma once
|
|
|
|
|
2023-05-13 17:09:51 +03:00
|
|
|
#include "ChunkHeader.h"
|
2023-05-13 15:08:23 +03:00
|
|
|
#include "Message.h"
|
|
|
|
#include "MessageHeader.h"
|
2023-05-13 16:20:41 +03:00
|
|
|
#include <AK/MemoryStream.h>
|
2023-05-13 17:24:53 +03:00
|
|
|
#include <AK/String.h>
|
2021-07-12 17:25:37 +03:00
|
|
|
#include <AK/Vector.h>
|
2023-05-13 16:20:41 +03:00
|
|
|
#include <LibCore/File.h>
|
2021-07-12 17:25:37 +03:00
|
|
|
#include <LibCore/Notifier.h>
|
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
namespace SpiceAgent {
|
|
|
|
|
2023-05-13 17:09:51 +03:00
|
|
|
// 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;
|
|
|
|
|
2021-07-12 17:25:37 +03:00
|
|
|
class SpiceAgent {
|
|
|
|
public:
|
2023-05-13 15:08:23 +03:00
|
|
|
static ErrorOr<NonnullOwnPtr<SpiceAgent>> create(StringView device_path);
|
2023-05-13 16:20:41 +03:00
|
|
|
SpiceAgent(NonnullOwnPtr<Core::File> spice_device, Vector<Capability> const& capabilities);
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
ErrorOr<void> start();
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
template<typename T>
|
|
|
|
ErrorOr<void> send_message(T message)
|
|
|
|
{
|
|
|
|
// Attempt to write the message's data to a stream.
|
|
|
|
auto message_stream = AK::AllocatingMemoryStream();
|
|
|
|
TRY(message.write_to_stream(message_stream));
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
// Create a header to be sent.
|
2023-05-13 17:09:51 +03:00
|
|
|
auto message_header_stream = AK::AllocatingMemoryStream();
|
|
|
|
auto message_header = MessageHeader(message.type(), message_stream.used_buffer_size());
|
|
|
|
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();
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
// 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.
|
2023-05-13 17:09:51 +03:00
|
|
|
auto chunk_header = ChunkHeader(ChunkHeader::Port::Client, length);
|
|
|
|
TRY(m_spice_device->write_value(chunk_header));
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
// The message's header.
|
2023-05-13 17:09:51 +03:00
|
|
|
TRY(m_spice_device->write_until_depleted(TRY(message_header_stream.read_until_eof())));
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
// The message content.
|
|
|
|
TRY(m_spice_device->write_until_depleted(TRY(message_stream.read_until_eof())));
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
return {};
|
|
|
|
}
|
2021-07-12 17:25:37 +03:00
|
|
|
|
|
|
|
private:
|
2023-05-13 15:08:23 +03:00
|
|
|
NonnullOwnPtr<Core::File> m_spice_device;
|
|
|
|
Vector<Capability> m_capabilities;
|
2021-07-12 17:25:37 +03:00
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
RefPtr<Core::Notifier> m_notifier;
|
2023-05-12 20:27:24 +03:00
|
|
|
|
2023-05-13 16:20:41 +03:00
|
|
|
// Fired when we receive clipboard data from the spice server.
|
|
|
|
ErrorOr<void> did_receive_clipboard_message(ClipboardMessage& message);
|
|
|
|
|
2023-05-13 15:08:23 +03:00
|
|
|
ErrorOr<void> on_message_received();
|
|
|
|
ErrorOr<ByteBuffer> read_message_buffer();
|
2021-07-12 17:25:37 +03:00
|
|
|
};
|
2023-05-13 15:08:23 +03:00
|
|
|
}
|