/* * Copyright (c) 2021, Kyle Pereira * Copyright (c) 2023, Caoimhe Byrne * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include "ChunkHeader.h" #include "FileTransferOperation.h" #include "Message.h" #include "MessageHeader.h" #include #include #include #include #include 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; // The maximum amount of data that can be received in one file transfer message constexpr u32 file_transfer_buffer_threshold = 65536; class SpiceAgent { public: static ErrorOr> create(StringView device_path); SpiceAgent(NonnullOwnPtr spice_device, Vector const& capabilities); ErrorOr start(); template ErrorOr 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)); // Create a header to be sent. 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(); // 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. auto chunk_header = ChunkHeader(ChunkHeader::Port::Client, length); TRY(m_spice_device->write_value(chunk_header)); // The message's header. TRY(m_spice_device->write_until_depleted(TRY(message_header_stream.read_until_eof()))); // The message content. TRY(m_spice_device->write_until_depleted(TRY(message_stream.read_until_eof()))); return {}; } Function on_disconnected_from_spice_server; private: NonnullOwnPtr m_spice_device; Vector m_capabilities; HashMap> m_file_transfer_operations; RefPtr m_notifier; bool m_clipboard_dirty { false }; // Fired when we receive clipboard data from the spice server. ErrorOr did_receive_clipboard_message(ClipboardMessage& message); // Fired when the user's clipboard changes ErrorOr on_clipboard_update(String const& mime_type); // Sends the GUI::Clipboard's current contents to the spice server ErrorOr send_clipboard_contents(ClipboardDataType data_type); ErrorOr on_message_received(); ErrorOr read_message_buffer(); }; }