blob: 2ea1893f6e23c54ee4f1cfb9ad12cfa7ed979b59 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
/*
* Copyright (c) 2021, Kyle Pereira <kyle@xylepereira.me>
* Copyright (c) 2023, Caoimhe Byrne <caoimhebyrne06@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include "ChunkHeader.h"
#include "Message.h"
#include "MessageHeader.h"
#include <AK/MemoryStream.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibCore/File.h>
#include <LibCore/Notifier.h>
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 {
public:
static ErrorOr<NonnullOwnPtr<SpiceAgent>> create(StringView device_path);
SpiceAgent(NonnullOwnPtr<Core::File> spice_device, Vector<Capability> const& capabilities);
ErrorOr<void> start();
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));
// 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 {};
}
private:
NonnullOwnPtr<Core::File> m_spice_device;
Vector<Capability> m_capabilities;
RefPtr<Core::Notifier> m_notifier;
bool m_clipboard_dirty { false };
// Fired when we receive clipboard data from the spice server.
ErrorOr<void> did_receive_clipboard_message(ClipboardMessage& message);
// Fired when the user's clipboard changes
ErrorOr<void> on_clipboard_update(String const& mime_type);
// Sends the GUI::Clipboard's current contents to the spice server
ErrorOr<void> send_clipboard_contents(ClipboardDataType data_type);
ErrorOr<void> on_message_received();
ErrorOr<ByteBuffer> read_message_buffer();
};
}
|