mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 21:47:23 +00:00
[client] spice: implement channel caps and initial clipboard support
This commit is contained in:
parent
00e07c0384
commit
108369414e
@ -138,4 +138,9 @@ SpiceMsgcMouseRelease;
|
|||||||
#define COMMON_SET_CAPABILITY(caps, index) \
|
#define COMMON_SET_CAPABILITY(caps, index) \
|
||||||
{ (caps)[(index) / 32] |= (1 << ((index) % 32)); }
|
{ (caps)[(index) / 32] |= (1 << ((index) % 32)); }
|
||||||
|
|
||||||
|
#define MAIN_CAPS_BYTES (((SPICE_MAIN_CAP_SEAMLESS_MIGRATE + 32) / 8) & ~3)
|
||||||
|
#define MAIN_SET_CAPABILITY(caps, index) \
|
||||||
|
{ (caps)[(index) / 32] |= (1 << ((index) % 32)); }
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
@ -134,7 +134,7 @@ bool spice_on_main_channel_read ();
|
|||||||
bool spice_on_inputs_channel_read();
|
bool spice_on_inputs_channel_read();
|
||||||
|
|
||||||
bool spice_agent_process ();
|
bool spice_agent_process ();
|
||||||
bool spice_agent_connect (bool startup);
|
bool spice_agent_connect ();
|
||||||
bool spice_agent_send_caps(bool request);
|
bool spice_agent_send_caps(bool request);
|
||||||
|
|
||||||
// thread safe read/write methods
|
// thread safe read/write methods
|
||||||
@ -420,8 +420,7 @@ bool spice_on_main_channel_read()
|
|||||||
|
|
||||||
spice.agentTokens = msg.agent_tokens;
|
spice.agentTokens = msg.agent_tokens;
|
||||||
spice.hasAgent = msg.agent_connected;
|
spice.hasAgent = msg.agent_connected;
|
||||||
|
if (spice.hasAgent && !spice_agent_connect())
|
||||||
if (spice.hasAgent && !spice_agent_connect(true))
|
|
||||||
{
|
{
|
||||||
spice_disconnect();
|
spice_disconnect();
|
||||||
DEBUG_ERROR("failed to connect to spice agent");
|
DEBUG_ERROR("failed to connect to spice agent");
|
||||||
@ -491,8 +490,33 @@ bool spice_on_main_channel_read()
|
|||||||
|
|
||||||
if (header.type == SPICE_MSG_MAIN_AGENT_CONNECTED)
|
if (header.type == SPICE_MSG_MAIN_AGENT_CONNECTED)
|
||||||
{
|
{
|
||||||
|
DEBUG_PROTO("SPICE_MSG_MAIN_AGENT_CONNECTED");
|
||||||
|
|
||||||
spice.hasAgent = true;
|
spice.hasAgent = true;
|
||||||
if (!spice_agent_connect(false))
|
if (!spice_agent_connect())
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("failed to connect to spice agent");
|
||||||
|
spice_disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.type == SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS)
|
||||||
|
{
|
||||||
|
DEBUG_PROTO("SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS");
|
||||||
|
|
||||||
|
uint32_t num_tokens;
|
||||||
|
if (!spice_read_nl(channel, &num_tokens, sizeof(num_tokens)))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("failed to read agent tokens");
|
||||||
|
spice_disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
spice.hasAgent = true;
|
||||||
|
spice.agentTokens = num_tokens;
|
||||||
|
if (!spice_agent_connect())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to connect to spice agent");
|
DEBUG_ERROR("failed to connect to spice agent");
|
||||||
spice_disconnect();
|
spice_disconnect();
|
||||||
@ -503,6 +527,8 @@ bool spice_on_main_channel_read()
|
|||||||
|
|
||||||
if (header.type == SPICE_MSG_MAIN_AGENT_DISCONNECTED)
|
if (header.type == SPICE_MSG_MAIN_AGENT_DISCONNECTED)
|
||||||
{
|
{
|
||||||
|
DEBUG_PROTO("SPICE_MSG_MAIN_AGENT_DISCONNECTED");
|
||||||
|
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
if (!spice_read_nl(channel, &error, sizeof(error)))
|
if (!spice_read_nl(channel, &error, sizeof(error)))
|
||||||
{
|
{
|
||||||
@ -516,8 +542,17 @@ bool spice_on_main_channel_read()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.type == SPICE_MSG_MAIN_AGENT_DATA && spice.hasAgent)
|
if (header.type == SPICE_MSG_MAIN_AGENT_DATA)
|
||||||
{
|
{
|
||||||
|
DEBUG_PROTO("SPICE_MSG_MAIN_AGENT_DATA");
|
||||||
|
|
||||||
|
if (!spice.hasAgent)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("recieved agent data when the agent is yet to be started");
|
||||||
|
spice_discard_nl(channel, header.size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!spice_agent_process())
|
if (!spice_agent_process())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to process spice agent message");
|
DEBUG_ERROR("failed to process spice agent message");
|
||||||
@ -650,18 +685,26 @@ bool spice_connect_channel(struct SpiceChannel * channel)
|
|||||||
channel->connected = true;
|
channel->connected = true;
|
||||||
|
|
||||||
uint32_t supportCaps[COMMON_CAPS_BYTES / sizeof(uint32_t)];
|
uint32_t supportCaps[COMMON_CAPS_BYTES / sizeof(uint32_t)];
|
||||||
|
uint32_t channelCaps[MAIN_CAPS_BYTES / sizeof(uint32_t)];
|
||||||
memset(supportCaps, 0, sizeof(supportCaps));
|
memset(supportCaps, 0, sizeof(supportCaps));
|
||||||
|
memset(channelCaps, 0, sizeof(channelCaps));
|
||||||
|
|
||||||
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
|
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
|
||||||
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_AUTH_SPICE );
|
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_AUTH_SPICE );
|
||||||
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_MINI_HEADER );
|
COMMON_SET_CAPABILITY(supportCaps, SPICE_COMMON_CAP_MINI_HEADER );
|
||||||
|
|
||||||
|
if (channel == &spice.scMain)
|
||||||
|
MAIN_SET_CAPABILITY(channelCaps, SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS);
|
||||||
|
|
||||||
SpiceLinkHeader header =
|
SpiceLinkHeader header =
|
||||||
{
|
{
|
||||||
.magic = SPICE_MAGIC ,
|
.magic = SPICE_MAGIC ,
|
||||||
.major_version = SPICE_VERSION_MAJOR,
|
.major_version = SPICE_VERSION_MAJOR,
|
||||||
.minor_version = SPICE_VERSION_MINOR,
|
.minor_version = SPICE_VERSION_MINOR,
|
||||||
.size = sizeof(SpiceLinkMess) + sizeof(supportCaps)
|
.size =
|
||||||
|
sizeof(SpiceLinkMess) +
|
||||||
|
sizeof(supportCaps ) +
|
||||||
|
sizeof(channelCaps )
|
||||||
};
|
};
|
||||||
|
|
||||||
SpiceLinkMess message =
|
SpiceLinkMess message =
|
||||||
@ -670,14 +713,15 @@ bool spice_connect_channel(struct SpiceChannel * channel)
|
|||||||
.channel_type = channel->channelType,
|
.channel_type = channel->channelType,
|
||||||
.channel_id = spice.channelID,
|
.channel_id = spice.channelID,
|
||||||
.num_common_caps = sizeof(supportCaps) / sizeof(uint32_t),
|
.num_common_caps = sizeof(supportCaps) / sizeof(uint32_t),
|
||||||
.num_channel_caps = 0,
|
.num_channel_caps = sizeof(channelCaps) / sizeof(uint32_t),
|
||||||
.caps_offset = sizeof(SpiceLinkMess)
|
.caps_offset = sizeof(SpiceLinkMess)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!spice_write_nl(channel, &header , sizeof(header )) ||
|
!spice_write_nl(channel, &header , sizeof(header )) ||
|
||||||
!spice_write_nl(channel, &message , sizeof(message )) ||
|
!spice_write_nl(channel, &message , sizeof(message )) ||
|
||||||
!spice_write_nl(channel, &supportCaps, sizeof(supportCaps))
|
!spice_write_nl(channel, &supportCaps, sizeof(supportCaps)) ||
|
||||||
|
!spice_write_nl(channel, &channelCaps, sizeof(channelCaps))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("failed to write the initial payload");
|
DEBUG_ERROR("failed to write the initial payload");
|
||||||
@ -801,9 +845,8 @@ void spice_disconnect_channel(struct SpiceChannel * channel)
|
|||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
bool spice_agent_connect(bool startup)
|
bool spice_agent_connect()
|
||||||
{
|
{
|
||||||
return true;
|
|
||||||
DEBUG_INFO("Spice agent available, sending start");
|
DEBUG_INFO("Spice agent available, sending start");
|
||||||
|
|
||||||
const uint32_t tokens = SPICE_AGENT_TOKENS_MAX;
|
const uint32_t tokens = SPICE_AGENT_TOKENS_MAX;
|
||||||
@ -813,11 +856,9 @@ bool spice_agent_connect(bool startup)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startup && !spice_agent_send_caps(startup))
|
if (!spice_agent_send_caps(true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//todo, agent setup
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -881,12 +922,13 @@ bool spice_agent_process()
|
|||||||
|
|
||||||
bool spice_agent_send_caps(bool request)
|
bool spice_agent_send_caps(bool request)
|
||||||
{
|
{
|
||||||
const ssize_t capsSize = (sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES);
|
const ssize_t capsSize = sizeof(VDAgentAnnounceCapabilities) + VD_AGENT_CAPS_BYTES;
|
||||||
VDAgentAnnounceCapabilities *caps = (VDAgentAnnounceCapabilities *)malloc(capsSize);
|
VDAgentAnnounceCapabilities *caps = (VDAgentAnnounceCapabilities *)malloc(capsSize);
|
||||||
memset(caps, 0, capsSize);
|
memset(caps, 0, capsSize);
|
||||||
|
|
||||||
caps->request = request ? 1 : 0;
|
caps->request = request ? 1 : 0;
|
||||||
VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
|
VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
|
||||||
|
VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
|
||||||
|
|
||||||
if (!spice_agent_write_msg(VD_AGENT_ANNOUNCE_CAPABILITIES, caps, capsSize))
|
if (!spice_agent_write_msg(VD_AGENT_ANNOUNCE_CAPABILITIES, caps, capsSize))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user