Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:GA
spice-vdagent
vdagentd-do-endian-swapping.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File vdagentd-do-endian-swapping.patch of Package spice-vdagent
From d28d5e97f08097fec6b3367ba87960810a742649 Mon Sep 17 00:00:00 2001 From: Michal Suchanek <msuchanek@suse.de> Date: Mon, 23 Jan 2017 14:53:53 +0100 Subject: [PATCH] Move mouse-specific handling out of virtio_port_read_complete Move some mouse-specific code from the start of virtio_port_read_complete to a separate helper as is the case with other message types. Signed-off-by: Michal Suchanek <msuchanek@suse.de> Acked-by: Christophe Fergeau <cfergeau@redhat.com> --- src/vdagentd.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) --- spice-vdagent-0.16.0.orig/src/vdagentd.c +++ spice-vdagent-0.16.0/src/vdagentd.c @@ -78,6 +78,34 @@ static int client_connected = 0; static int max_clipboard = -1; /* utility functions */ +static void virtio_msg_uint32_to_le(uint8_t *_msg, uint32_t size, uint32_t offset) +{ + uint32_t i, *msg = (uint32_t *)(_msg + offset); + + /* offset - size % 4 should be 0 - extra bytes are ignored */ + for (i = 0; i < (size - offset) / 4; i++) + msg[i] = GUINT32_TO_LE(msg[i]); +} + +static void virtio_msg_uint32_from_le(uint8_t *_msg, uint32_t size, uint32_t offset) +{ + uint32_t i, *msg = (uint32_t *)(_msg + offset); + + /* offset - size % 4 should be 0 - extra bytes are ignored */ + for (i = 0; i < (size - offset) / 4; i++) + msg[i] = GUINT32_FROM_LE(msg[i]); +} + +static void virtio_msg_uint16_from_le(uint8_t *_msg, uint32_t size, uint32_t offset) +{ + uint32_t i; + uint16_t *msg = (uint16_t *)(_msg + offset); + + /* offset - size % 2 should be 0 - extra bytes are ignored */ + for (i = 0; i < (size - offset) / 2; i++) + msg[i] = GUINT16_FROM_LE(msg[i]); +} + /* vdagentd <-> spice-client communication handling */ static void send_capabilities(struct vdagent_virtio_port *vport, uint32_t request) @@ -102,6 +130,7 @@ static void send_capabilities(struct vda VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD); VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC); + virtio_msg_uint32_to_le((uint8_t *)caps, size, 0); vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, VD_AGENT_ANNOUNCE_CAPABILITIES, 0, @@ -118,6 +147,29 @@ static void do_client_disconnect(void) } } +void do_client_mouse(struct vdagentd_uinput **uinputp, VDAgentMouseState *mouse) +{ + vdagentd_uinput_do_mouse(uinputp, mouse); + if (!*uinputp) { + /* Try to re-open the tablet */ + struct agent_data *agent_data = + udscs_get_user_data(active_session_conn); + if (agent_data) + *uinputp = vdagentd_uinput_create(uinput_device, + agent_data->width, + agent_data->height, + agent_data->screen_info, + agent_data->screen_count, + debug > 1, + uinput_fake); + if (!*uinputp) { + syslog(LOG_CRIT, "Fatal uinput error"); + retval = 1; + quit = 1; + } + } +} + static void do_client_monitors(struct vdagent_virtio_port *vport, int port_nr, VDAgentMessage *message_header, VDAgentMonitorsConfig *new_monitors) { @@ -151,8 +203,8 @@ static void do_client_monitors(struct vd (uint8_t *)mon_config, size); /* Acknowledge reception of monitors config to spice server / client */ - reply.type = VD_AGENT_MONITORS_CONFIG; - reply.error = VD_AGENT_SUCCESS; + reply.type = GUINT32_TO_LE(VD_AGENT_MONITORS_CONFIG); + reply.error = GUINT32_TO_LE(VD_AGENT_SUCCESS); vdagent_virtio_port_write(vport, port_nr, VD_AGENT_REPLY, 0, (uint8_t *)&reply, sizeof(reply)); } @@ -253,8 +305,8 @@ static void cancel_file_xfer(struct vdag const char *msg, uint32_t id) { VDAgentFileXferStatusMessage status = { - .id = id, - .result = VD_AGENT_FILE_XFER_STATUS_CANCELLED, + .id = GUINT32_TO_LE(id), + .result = GUINT32_TO_LE(VD_AGENT_FILE_XFER_STATUS_CANCELLED), }; syslog(LOG_WARNING, msg, id); if (vport) @@ -296,6 +348,8 @@ static void do_client_file_xfer(struct v id = d->id; break; } + default: + g_return_if_reached(); /* quiet uninitialized variable warning */ } conn = g_hash_table_lookup(active_xfers, GUINT_TO_POINTER(id)); @@ -307,52 +361,156 @@ static void do_client_file_xfer(struct v udscs_write(conn, msg_type, 0, 0, data, message_header->size); } -int virtio_port_read_complete( - struct vdagent_virtio_port *vport, - int port_nr, - VDAgentMessage *message_header, +static gsize vdagent_message_min_size[] = +{ + -1, /* Does not exist */ + sizeof(VDAgentMouseState), /* VD_AGENT_MOUSE_STATE */ + sizeof(VDAgentMonitorsConfig), /* VD_AGENT_MONITORS_CONFIG */ + sizeof(VDAgentReply), /* VD_AGENT_REPLY */ + sizeof(VDAgentClipboard), /* VD_AGENT_CLIPBOARD */ + sizeof(VDAgentDisplayConfig), /* VD_AGENT_DISPLAY_CONFIG */ + sizeof(VDAgentAnnounceCapabilities), /* VD_AGENT_ANNOUNCE_CAPABILITIES */ + sizeof(VDAgentClipboardGrab), /* VD_AGENT_CLIPBOARD_GRAB */ + sizeof(VDAgentClipboardRequest), /* VD_AGENT_CLIPBOARD_REQUEST */ + sizeof(VDAgentClipboardRelease), /* VD_AGENT_CLIPBOARD_RELEASE */ + sizeof(VDAgentFileXferStartMessage), /* VD_AGENT_FILE_XFER_START */ + sizeof(VDAgentFileXferStatusMessage), /* VD_AGENT_FILE_XFER_STATUS */ + sizeof(VDAgentFileXferDataMessage), /* VD_AGENT_FILE_XFER_DATA */ + 0, /* VD_AGENT_CLIENT_DISCONNECTED */ + sizeof(VDAgentMaxClipboard), /* VD_AGENT_MAX_CLIPBOARD */ + sizeof(VDAgentAudioVolumeSync), /* VD_AGENT_AUDIO_VOLUME_SYNC */ +}; + +static void vdagent_message_clipboard_from_le(VDAgentMessage *message_header, + uint8_t *data) +{ + gsize min_size = vdagent_message_min_size[message_header->type]; + uint32_t *data_type = (uint32_t *) data; + + if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, + VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + min_size += 4; + data_type++; + } + + switch (message_header->type) { + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD: + *data_type = GUINT32_FROM_LE(*data_type); + break; + case VD_AGENT_CLIPBOARD_GRAB: + virtio_msg_uint32_from_le(data, message_header->size, min_size); + break; + case VD_AGENT_CLIPBOARD_RELEASE: + break; + default: + g_warn_if_reached(); + } +} + +static void vdagent_message_file_xfer_from_le(VDAgentMessage *message_header, uint8_t *data) { + uint32_t *id = (uint32_t *)data; + *id = GUINT32_FROM_LE(*id); + id++; /* status */ + + switch (message_header->type) { + case VD_AGENT_FILE_XFER_DATA: { + VDAgentFileXferDataMessage *msg = (VDAgentFileXferDataMessage *)data; + msg->size = GUINT64_FROM_LE(msg->size); + break; + } + case VD_AGENT_FILE_XFER_STATUS: + *id = GUINT32_FROM_LE(*id); /* status */ + break; + } +} + +static gboolean vdagent_message_check_size(const VDAgentMessage *message_header) +{ uint32_t min_size = 0; if (message_header->protocol != VD_AGENT_PROTOCOL) { syslog(LOG_ERR, "message with wrong protocol version ignoring"); - return 0; + return FALSE; + } + + if (!message_header->type || + message_header->type >= G_N_ELEMENTS(vdagent_message_min_size)) { + syslog(LOG_WARNING, "unknown message type %d, ignoring", + message_header->type); + return FALSE; + } + + min_size = vdagent_message_min_size[message_header->type]; + if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, + VD_AGENT_CAP_CLIPBOARD_SELECTION)) { + switch (message_header->type) { + case VD_AGENT_CLIPBOARD_GRAB: + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_RELEASE: + min_size += 4; + } } switch (message_header->type) { + case VD_AGENT_MONITORS_CONFIG: + case VD_AGENT_FILE_XFER_START: + case VD_AGENT_FILE_XFER_DATA: + case VD_AGENT_CLIPBOARD: + case VD_AGENT_CLIPBOARD_GRAB: + case VD_AGENT_AUDIO_VOLUME_SYNC: + case VD_AGENT_ANNOUNCE_CAPABILITIES: + if (message_header->size < min_size) { + syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", + message_header->size, message_header->type); + return FALSE; + } + break; case VD_AGENT_MOUSE_STATE: - if (message_header->size != sizeof(VDAgentMouseState)) - goto size_error; - vdagentd_uinput_do_mouse(&uinput, (VDAgentMouseState *)data); - if (!uinput) { - /* Try to re-open the tablet */ - struct agent_data *agent_data = - udscs_get_user_data(active_session_conn); - if (agent_data) - uinput = vdagentd_uinput_create(uinput_device, - agent_data->width, - agent_data->height, - agent_data->screen_info, - agent_data->screen_count, - debug > 1, - uinput_fake); - if (!uinput) { - syslog(LOG_CRIT, "Fatal uinput error"); - retval = 1; - quit = 1; - } + case VD_AGENT_FILE_XFER_STATUS: + case VD_AGENT_DISPLAY_CONFIG: + case VD_AGENT_REPLY: + case VD_AGENT_CLIPBOARD_REQUEST: + case VD_AGENT_CLIPBOARD_RELEASE: + case VD_AGENT_MAX_CLIPBOARD: + case VD_AGENT_CLIENT_DISCONNECTED: + if (message_header->size != min_size) { + syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", + message_header->size, message_header->type); + return FALSE; } break; + default: + g_warn_if_reached(); + return FALSE; + } + return TRUE; +} + +int virtio_port_read_complete( + struct vdagent_virtio_port *vport, + int port_nr, + VDAgentMessage *message_header, + uint8_t *data) +{ + if (!vdagent_message_check_size(message_header)) + return 0; + + switch (message_header->type) { + case VD_AGENT_MOUSE_STATE: + virtio_msg_uint32_from_le(data, message_header->size, 0); + do_client_mouse(&uinput, (VDAgentMouseState *)data); + break; case VD_AGENT_MONITORS_CONFIG: - if (message_header->size < sizeof(VDAgentMonitorsConfig)) - goto size_error; + virtio_msg_uint32_from_le(data, message_header->size, 0); do_client_monitors(vport, port_nr, message_header, (VDAgentMonitorsConfig *)data); break; case VD_AGENT_ANNOUNCE_CAPABILITIES: - if (message_header->size < sizeof(VDAgentAnnounceCapabilities)) - goto size_error; + virtio_msg_uint32_from_le(data, message_header->size, 0); do_client_capabilities(vport, message_header, (VDAgentAnnounceCapabilities *)data); break; @@ -360,61 +518,41 @@ int virtio_port_read_complete( case VD_AGENT_CLIPBOARD_REQUEST: case VD_AGENT_CLIPBOARD: case VD_AGENT_CLIPBOARD_RELEASE: - switch (message_header->type) { - case VD_AGENT_CLIPBOARD_GRAB: - min_size = sizeof(VDAgentClipboardGrab); break; - case VD_AGENT_CLIPBOARD_REQUEST: - min_size = sizeof(VDAgentClipboardRequest); break; - case VD_AGENT_CLIPBOARD: - min_size = sizeof(VDAgentClipboard); break; - } - if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size, - VD_AGENT_CAP_CLIPBOARD_SELECTION)) { - min_size += 4; - } - if (message_header->size < min_size) { - goto size_error; - } + vdagent_message_clipboard_from_le(message_header, data); do_client_clipboard(vport, message_header, data); break; case VD_AGENT_FILE_XFER_START: case VD_AGENT_FILE_XFER_STATUS: case VD_AGENT_FILE_XFER_DATA: + vdagent_message_file_xfer_from_le(message_header, data); do_client_file_xfer(vport, message_header, data); break; case VD_AGENT_CLIENT_DISCONNECTED: vdagent_virtio_port_reset(vport, VDP_CLIENT_PORT); do_client_disconnect(); break; - case VD_AGENT_MAX_CLIPBOARD: - if (message_header->size != sizeof(VDAgentMaxClipboard)) - goto size_error; - VDAgentMaxClipboard *msg = (VDAgentMaxClipboard *)data; - syslog(LOG_DEBUG, "Set max clipboard: %d", msg->max); - max_clipboard = msg->max; + case VD_AGENT_MAX_CLIPBOARD: { + max_clipboard = GUINT32_FROM_LE(((VDAgentMaxClipboard *)data)->max); + syslog(LOG_DEBUG, "Set max clipboard: %d", max_clipboard); break; - case VD_AGENT_AUDIO_VOLUME_SYNC: - if (message_header->size < sizeof(VDAgentAudioVolumeSync)) - goto size_error; + } + case VD_AGENT_AUDIO_VOLUME_SYNC: { + VDAgentAudioVolumeSync *vdata = (VDAgentAudioVolumeSync *)data; + virtio_msg_uint16_from_le((uint8_t *)vdata, message_header->size, + offsetof(VDAgentAudioVolumeSync, volume)); - do_client_volume_sync(vport, port_nr, message_header, - (VDAgentAudioVolumeSync *)data); + do_client_volume_sync(vport, port_nr, message_header, vdata); break; + } default: - syslog(LOG_WARNING, "unknown message type %d, ignoring", - message_header->type); + g_warn_if_reached(); } return 0; - -size_error: - syslog(LOG_ERR, "read: invalid message size: %u for message type: %u", - message_header->size, message_header->type); - return 0; } static void virtio_write_clipboard(uint8_t selection, uint32_t msg_type, - uint32_t data_type, const uint8_t *data, uint32_t data_size) + uint32_t data_type, uint8_t *data, uint32_t data_size) { uint32_t size = data_size; @@ -435,15 +573,18 @@ static void virtio_write_clipboard(uint8 vdagent_virtio_port_write_append(virtio_port, sel, 4); } if (data_type != -1) { + data_type = GUINT32_TO_LE(data_type); vdagent_virtio_port_write_append(virtio_port, (uint8_t*)&data_type, 4); } + if (msg_type == VD_AGENT_CLIPBOARD_GRAB) + virtio_msg_uint32_to_le(data, data_size, 0); vdagent_virtio_port_write_append(virtio_port, data, data_size); } /* vdagentd <-> vdagent communication handling */ int do_agent_clipboard(struct udscs_connection *conn, - struct udscs_message_header *header, const uint8_t *data) + struct udscs_message_header *header, uint8_t *data) { uint8_t selection = header->arg1; uint32_t msg_type = 0, data_type = -1, size = header->size; @@ -746,8 +887,8 @@ void agent_read_complete(struct udscs_co break; case VDAGENTD_FILE_XFER_STATUS:{ VDAgentFileXferStatusMessage status; - status.id = header->arg1; - status.result = header->arg2; + status.id = GUINT32_TO_LE(header->arg1); + status.result = GUINT32_TO_LE(header->arg2); vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT, VD_AGENT_FILE_XFER_STATUS, 0, (uint8_t *)&status, sizeof(status)); --- spice-vdagent-0.16.0.orig/src/vdagent-virtio-port.c +++ spice-vdagent-0.16.0/src/vdagent-virtio-port.c @@ -28,6 +28,7 @@ #include <sys/select.h> #include <sys/socket.h> #include <sys/un.h> +#include <glib.h> #include "vdagent-virtio-port.h" @@ -217,16 +218,16 @@ int vdagent_virtio_port_write_start( return -1; } - chunk_header.port = port_nr; - chunk_header.size = sizeof(message_header) + data_size; + chunk_header.port = GUINT32_TO_LE(port_nr); + chunk_header.size = GUINT32_TO_LE(sizeof(message_header) + data_size); memcpy(new_wbuf->buf + new_wbuf->write_pos, &chunk_header, sizeof(chunk_header)); new_wbuf->write_pos += sizeof(chunk_header); - - message_header.protocol = VD_AGENT_PROTOCOL; - message_header.type = message_type; - message_header.opaque = message_opaque; - message_header.size = data_size; + + message_header.protocol = GUINT32_TO_LE(VD_AGENT_PROTOCOL); + message_header.type = GUINT32_TO_LE(message_type); + message_header.opaque = GUINT64_TO_LE(message_opaque); + message_header.size = GUINT32_TO_LE(data_size); memcpy(new_wbuf->buf + new_wbuf->write_pos, &message_header, sizeof(message_header)); new_wbuf->write_pos += sizeof(message_header); @@ -310,13 +311,20 @@ static void vdagent_virtio_port_do_chunk memcpy((uint8_t *)&port->message_header + port->message_header_read, vport->chunk_data, read); port->message_header_read += read; - if (port->message_header_read == sizeof(port->message_header) && - port->message_header.size) { - port->message_data = malloc(port->message_header.size); - if (!port->message_data) { - syslog(LOG_ERR, "out of memory, disconnecting virtio"); - vdagent_virtio_port_destroy(vportp); - return; + if (port->message_header_read == sizeof(port->message_header)) { + + port->message_header.protocol = GUINT32_FROM_LE(port->message_header.protocol); + port->message_header.type = GUINT32_FROM_LE(port->message_header.type); + port->message_header.opaque = GUINT64_FROM_LE(port->message_header.opaque); + port->message_header.size = GUINT32_FROM_LE(port->message_header.size); + + if (port->message_header.size) { + port->message_data = malloc(port->message_header.size); + if (!port->message_data) { + syslog(LOG_ERR, "out of memory, disconnecting virtio"); + vdagent_virtio_port_destroy(vportp); + return; + } } } pos = read; @@ -421,6 +429,8 @@ static void vdagent_virtio_port_do_read( if (vport->chunk_header_read < sizeof(vport->chunk_header)) { vport->chunk_header_read += n; if (vport->chunk_header_read == sizeof(vport->chunk_header)) { + vport->chunk_header.size = GUINT32_FROM_LE(vport->chunk_header.size); + vport->chunk_header.port = GUINT32_FROM_LE(vport->chunk_header.port); if (vport->chunk_header.size > VD_AGENT_MAX_DATA_SIZE) { syslog(LOG_ERR, "chunk size %u too large", vport->chunk_header.size);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor