mirror of
				https://github.com/gnif/LookingGlass.git
				synced 2025-11-04 14:41:55 +00:00 
			
		
		
		
	[client] spice: implement channel caps and initial clipboard support
This commit is contained in:
		@@ -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))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user