mirror of
				https://github.com/gnif/LookingGlass.git
				synced 2025-11-04 06:31:54 +00:00 
			
		
		
		
	[client] spice: correct sending of large va agent buffers
This commit is contained in:
		@@ -54,6 +54,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
 | 
			
		||||
  #define DEBUG_KEYBOARD(fmt, args...) do {} while(0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_SPICE_CLIPBOARD
 | 
			
		||||
  #define DEBUG_CLIPBOARD(fmt, args...) DEBUG_PRINT("[C]", fmt, ##args)
 | 
			
		||||
#else
 | 
			
		||||
  #define DEBUG_CLIPBOARD(fmt, args...) do {} while(0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// we don't really need flow control because we are all local
 | 
			
		||||
// instead do what the spice-gtk library does and provide the largest
 | 
			
		||||
// possible number
 | 
			
		||||
@@ -160,7 +166,7 @@ static SpiceDataType agent_type_to_spice_type(uint32_t type);
 | 
			
		||||
 | 
			
		||||
// thread safe read/write methods
 | 
			
		||||
bool spice_write_msg       (struct SpiceChannel * channel, uint32_t type, const void * buffer, const ssize_t size);
 | 
			
		||||
bool spice_agent_write_msg (uint32_t type, const void * buffer, const ssize_t size);
 | 
			
		||||
bool spice_agent_write_msg (uint32_t type, const void * buffer, ssize_t size);
 | 
			
		||||
 | 
			
		||||
// non thread safe read/write methods (nl = non-locking)
 | 
			
		||||
bool    spice_read_nl     (const struct SpiceChannel * channel, void * buffer, const ssize_t size);
 | 
			
		||||
@@ -1018,7 +1024,7 @@ bool spice_agent_process(uint32_t dataSize)
 | 
			
		||||
 | 
			
		||||
      if (msg.type == VD_AGENT_CLIPBOARD_RELEASE)
 | 
			
		||||
      {
 | 
			
		||||
        DEBUG_PROTO("VD_AGENT_CLIPBOARD_RELEASE");
 | 
			
		||||
        DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_RELEASE");
 | 
			
		||||
        spice.cbAgentGrabbed = false;
 | 
			
		||||
        if (spice.cbReleaseFn)
 | 
			
		||||
          spice.cbReleaseFn();
 | 
			
		||||
@@ -1038,7 +1044,7 @@ bool spice_agent_process(uint32_t dataSize)
 | 
			
		||||
 | 
			
		||||
        if (msg.type == VD_AGENT_CLIPBOARD)
 | 
			
		||||
        {
 | 
			
		||||
          DEBUG_PROTO("VD_AGENT_CLIPBOARD");
 | 
			
		||||
          DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD");
 | 
			
		||||
          if (spice.cbBuffer)
 | 
			
		||||
          {
 | 
			
		||||
            DEBUG_ERROR("cbBuffer was never freed");
 | 
			
		||||
@@ -1070,7 +1076,7 @@ bool spice_agent_process(uint32_t dataSize)
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
          DEBUG_PROTO("VD_AGENT_CLIPBOARD_REQUEST");
 | 
			
		||||
          DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_REQUEST");
 | 
			
		||||
          if (spice.cbRequestFn)
 | 
			
		||||
            spice.cbRequestFn(agent_type_to_spice_type(type));
 | 
			
		||||
          return true;
 | 
			
		||||
@@ -1078,7 +1084,7 @@ bool spice_agent_process(uint32_t dataSize)
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        DEBUG_PROTO("VD_AGENT_CLIPBOARD_GRAB");
 | 
			
		||||
        DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_GRAB");
 | 
			
		||||
        if (remaining == 0)
 | 
			
		||||
          return true;
 | 
			
		||||
 | 
			
		||||
@@ -1092,8 +1098,9 @@ bool spice_agent_process(uint32_t dataSize)
 | 
			
		||||
        // there is zero documentation on the types field, it might be a bitfield
 | 
			
		||||
        // but for now we are going to assume it's not.
 | 
			
		||||
 | 
			
		||||
        spice.cbType         = agent_type_to_spice_type(types[0]);
 | 
			
		||||
        spice.cbAgentGrabbed = true;
 | 
			
		||||
        spice.cbType          = agent_type_to_spice_type(types[0]);
 | 
			
		||||
        spice.cbAgentGrabbed  = true;
 | 
			
		||||
        spice.cbClientGrabbed = false;
 | 
			
		||||
        if (spice.cbSelection)
 | 
			
		||||
        {
 | 
			
		||||
          // Windows doesnt support this, so until it's needed there is no point messing with it
 | 
			
		||||
@@ -1154,7 +1161,7 @@ bool spice_agent_send_caps(bool request)
 | 
			
		||||
 | 
			
		||||
// ============================================================================
 | 
			
		||||
 | 
			
		||||
bool spice_agent_write_msg(uint32_t type, const void * buffer, const ssize_t size)
 | 
			
		||||
bool spice_agent_write_msg(uint32_t type, const void * buffer, ssize_t size)
 | 
			
		||||
{
 | 
			
		||||
  VDAgentMessage msg;
 | 
			
		||||
  msg.protocol = VD_AGENT_PROTOCOL;
 | 
			
		||||
@@ -1163,21 +1170,40 @@ bool spice_agent_write_msg(uint32_t type, const void * buffer, const ssize_t siz
 | 
			
		||||
  msg.size     = size;
 | 
			
		||||
 | 
			
		||||
  LG_LOCK(spice.scMain.lock);
 | 
			
		||||
  if (!spice_write_msg_nl(&spice.scMain, SPICE_MSGC_MAIN_AGENT_DATA, &msg, sizeof(msg), size))
 | 
			
		||||
 | 
			
		||||
  uint8_t * buf   = (uint8_t *)buffer;
 | 
			
		||||
  ssize_t toWrite = size > VD_AGENT_MAX_DATA_SIZE - sizeof(msg) ? VD_AGENT_MAX_DATA_SIZE - sizeof(msg) : size;
 | 
			
		||||
  if (!spice_write_msg_nl(&spice.scMain, SPICE_MSGC_MAIN_AGENT_DATA, &msg, sizeof(msg), toWrite))
 | 
			
		||||
  {
 | 
			
		||||
    LG_UNLOCK(spice.scMain.lock);
 | 
			
		||||
    DEBUG_ERROR("failed to write agent data header");
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (buffer && size)
 | 
			
		||||
  bool first = true;
 | 
			
		||||
  while(toWrite)
 | 
			
		||||
  {
 | 
			
		||||
    if (spice_write_nl(&spice.scMain, buffer, size) != size)
 | 
			
		||||
    bool ok = false;
 | 
			
		||||
    if (first)
 | 
			
		||||
    {
 | 
			
		||||
      ok    = spice_write_nl(&spice.scMain, buf, toWrite) == toWrite;
 | 
			
		||||
      first = false;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      ok = spice_write_msg_nl(&spice.scMain, SPICE_MSGC_MAIN_AGENT_DATA, buf, toWrite, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!ok)
 | 
			
		||||
    {
 | 
			
		||||
      LG_UNLOCK(spice.scMain.lock);
 | 
			
		||||
      DEBUG_ERROR("failed to write agent data payload");
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size   -= toWrite;
 | 
			
		||||
    buf    += toWrite;
 | 
			
		||||
    toWrite = size > VD_AGENT_MAX_DATA_SIZE ? VD_AGENT_MAX_DATA_SIZE : size;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  LG_UNLOCK(spice.scMain.lock);
 | 
			
		||||
@@ -1542,10 +1568,6 @@ bool spice_set_clipboard_cb(SpiceClipboardNotice cbNoticeFn, SpiceClipboardData
 | 
			
		||||
 | 
			
		||||
bool spice_clipboard_grab(SpiceDataType type)
 | 
			
		||||
{
 | 
			
		||||
  // release first if we have grabbed previously
 | 
			
		||||
  if (spice.cbClientGrabbed && !spice_clipboard_release())
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  if (type == SPICE_DATA_NONE)
 | 
			
		||||
  {
 | 
			
		||||
    DEBUG_ERROR("grab type is invalid");
 | 
			
		||||
@@ -1614,7 +1636,7 @@ bool spice_clipboard_release()
 | 
			
		||||
bool spice_clipboard_data(SpiceDataType type, uint8_t * data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t * buffer;
 | 
			
		||||
  uint8_t bufSize;
 | 
			
		||||
  size_t    bufSize;
 | 
			
		||||
 | 
			
		||||
  if (spice.cbSelection)
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user