[client] spice: correct sending of large va agent buffers

This commit is contained in:
Geoffrey McRae 2019-02-24 15:35:17 +11:00
parent b368873f4d
commit 03628505ed

View File

@ -54,6 +54,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#define DEBUG_KEYBOARD(fmt, args...) do {} while(0) #define DEBUG_KEYBOARD(fmt, args...) do {} while(0)
#endif #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 // we don't really need flow control because we are all local
// instead do what the spice-gtk library does and provide the largest // instead do what the spice-gtk library does and provide the largest
// possible number // possible number
@ -160,7 +166,7 @@ static SpiceDataType agent_type_to_spice_type(uint32_t type);
// thread safe read/write methods // thread safe read/write methods
bool spice_write_msg (struct SpiceChannel * channel, uint32_t type, const void * buffer, const ssize_t size); 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) // non thread safe read/write methods (nl = non-locking)
bool spice_read_nl (const struct SpiceChannel * channel, void * buffer, const ssize_t size); 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) if (msg.type == VD_AGENT_CLIPBOARD_RELEASE)
{ {
DEBUG_PROTO("VD_AGENT_CLIPBOARD_RELEASE"); DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_RELEASE");
spice.cbAgentGrabbed = false; spice.cbAgentGrabbed = false;
if (spice.cbReleaseFn) if (spice.cbReleaseFn)
spice.cbReleaseFn(); spice.cbReleaseFn();
@ -1038,7 +1044,7 @@ bool spice_agent_process(uint32_t dataSize)
if (msg.type == VD_AGENT_CLIPBOARD) if (msg.type == VD_AGENT_CLIPBOARD)
{ {
DEBUG_PROTO("VD_AGENT_CLIPBOARD"); DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD");
if (spice.cbBuffer) if (spice.cbBuffer)
{ {
DEBUG_ERROR("cbBuffer was never freed"); DEBUG_ERROR("cbBuffer was never freed");
@ -1070,7 +1076,7 @@ bool spice_agent_process(uint32_t dataSize)
} }
else else
{ {
DEBUG_PROTO("VD_AGENT_CLIPBOARD_REQUEST"); DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_REQUEST");
if (spice.cbRequestFn) if (spice.cbRequestFn)
spice.cbRequestFn(agent_type_to_spice_type(type)); spice.cbRequestFn(agent_type_to_spice_type(type));
return true; return true;
@ -1078,7 +1084,7 @@ bool spice_agent_process(uint32_t dataSize)
} }
else else
{ {
DEBUG_PROTO("VD_AGENT_CLIPBOARD_GRAB"); DEBUG_CLIPBOARD("VD_AGENT_CLIPBOARD_GRAB");
if (remaining == 0) if (remaining == 0)
return true; 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 // there is zero documentation on the types field, it might be a bitfield
// but for now we are going to assume it's not. // but for now we are going to assume it's not.
spice.cbType = agent_type_to_spice_type(types[0]); spice.cbType = agent_type_to_spice_type(types[0]);
spice.cbAgentGrabbed = true; spice.cbAgentGrabbed = true;
spice.cbClientGrabbed = false;
if (spice.cbSelection) if (spice.cbSelection)
{ {
// Windows doesnt support this, so until it's needed there is no point messing with it // 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; VDAgentMessage msg;
msg.protocol = VD_AGENT_PROTOCOL; 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; msg.size = size;
LG_LOCK(spice.scMain.lock); 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); LG_UNLOCK(spice.scMain.lock);
DEBUG_ERROR("failed to write agent data header"); DEBUG_ERROR("failed to write agent data header");
return false; 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); LG_UNLOCK(spice.scMain.lock);
DEBUG_ERROR("failed to write agent data payload"); DEBUG_ERROR("failed to write agent data payload");
return false; return false;
} }
size -= toWrite;
buf += toWrite;
toWrite = size > VD_AGENT_MAX_DATA_SIZE ? VD_AGENT_MAX_DATA_SIZE : size;
} }
LG_UNLOCK(spice.scMain.lock); LG_UNLOCK(spice.scMain.lock);
@ -1542,10 +1568,6 @@ bool spice_set_clipboard_cb(SpiceClipboardNotice cbNoticeFn, SpiceClipboardData
bool spice_clipboard_grab(SpiceDataType type) 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) if (type == SPICE_DATA_NONE)
{ {
DEBUG_ERROR("grab type is invalid"); 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) bool spice_clipboard_data(SpiceDataType type, uint8_t * data, size_t size)
{ {
uint8_t * buffer; uint8_t * buffer;
uint8_t bufSize; size_t bufSize;
if (spice.cbSelection) if (spice.cbSelection)
{ {