[Spice-devel] [RFC PATCH vd_agent 3/3] Receive the graphics_device_info message
Lukáš Hrázký
lhrazky at redhat.com
Wed Nov 7 17:23:07 UTC 2018
The graphics_device_info message contains the device display ID
information (device address and device display ID). Stores the data in a
hash table in vdagent.
Signed-off-by: Lukáš Hrázký <lhrazky at redhat.com>
---
src/vdagent/vdagent.c | 69 ++++++++++++++++++++++++++++++++++++
src/vdagentd-proto-strings.h | 1 +
src/vdagentd-proto.h | 1 +
src/vdagentd/vdagentd.c | 16 +++++++++
4 files changed, 87 insertions(+)
diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index f7c8b72..d1af57f 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -53,6 +53,7 @@ typedef struct VDAgent {
struct vdagent_file_xfers *xfers;
struct udscs_connection *conn;
GIOChannel *x11_channel;
+ GHashTable *graphics_display_infos;
GMainLoop *loop;
} VDAgent;
@@ -95,6 +96,16 @@ static GOptionEntry entries[] = {
{ NULL }
};
+typedef struct GraphicsDisplayInfo {
+ char device_address[256];
+ uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+static void graphics_display_info_destroy(gpointer gdi)
+{
+ g_free(gdi);
+}
+
/**
* xfer_get_download_directory
*
@@ -159,6 +170,55 @@ static gboolean vdagent_finalize_file_xfer(VDAgent *agent)
return TRUE;
}
+static void vdagent_handle_graphics_device_info(VDAgent *agent, uint8_t *data, size_t size)
+{
+ VDAgentGraphicsDeviceInfos *graphics_device_infos = (VDAgentGraphicsDeviceInfos *)data;
+ VDAgentGraphicsDeviceInfo *graphics_device_info = graphics_device_infos->graphics_device_infos;
+
+ void *buffer_end = data + size;
+
+ syslog(LOG_INFO, "Received Graphics Device Info:");
+
+ for (size_t i = 0; i < graphics_device_infos->count; ++i) {
+ if ((void*) graphics_device_info > buffer_end ||
+ (void*) (&graphics_device_info->device_address +
+ graphics_device_info->device_address_len) > buffer_end) {
+ syslog(LOG_ERR, "Malformed graphics_display_info message, "
+ "extends beyond the end of the buffer");
+ break;
+ }
+
+ syslog(LOG_INFO, " channel_id: %u monitor_id: %u device_address: %s, "
+ "device_display_id: %u",
+ graphics_device_info->channel_id,
+ graphics_device_info->monitor_id,
+ graphics_device_info->device_address,
+ graphics_device_info->device_display_id);
+
+ GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+
+ size_t device_address_len = graphics_device_info->device_address_len;
+ if (device_address_len > sizeof(value->device_address)) {
+ syslog(LOG_ERR, "Received a device address longer than %lu, "
+ "will be truncated!", device_address_len);
+ device_address_len = sizeof(value->device_address);
+ }
+
+ strncpy(value->device_address,
+ (char*) graphics_device_info->device_address,
+ device_address_len);
+ value->device_address[device_address_len] = '\0'; // make sure the string is terminated
+ value->device_display_id = graphics_device_info->device_display_id;
+
+ g_hash_table_insert(agent->graphics_display_infos,
+ GUINT_TO_POINTER(graphics_device_info->channel_id + graphics_device_info->monitor_id),
+ value);
+
+ graphics_device_info = (VDAgentGraphicsDeviceInfo*) ((char*) graphics_device_info +
+ sizeof(VDAgentGraphicsDeviceInfo) + graphics_device_info->device_address_len);
+ }
+}
+
static void vdagent_quit_loop(VDAgent *agent)
{
/* other GMainLoop(s) might be running, quit them before agent->loop */
@@ -243,6 +303,9 @@ static void daemon_read_complete(struct udscs_connection **connp,
((VDAgentFileXferDataMessage *)data)->id);
}
break;
+ case VDAGENTD_GRAPHICS_DEVICE_INFO:
+ vdagent_handle_graphics_device_info(agent, data, header->size);
+ break;
case VDAGENTD_CLIENT_DISCONNECTED:
vdagent_clipboards_release_all(agent->clipboards);
if (vdagent_finalize_file_xfer(agent)) {
@@ -345,6 +408,11 @@ static VDAgent *vdagent_new(void)
g_unix_signal_add(SIGHUP, vdagent_signal_handler, agent);
g_unix_signal_add(SIGTERM, vdagent_signal_handler, agent);
+ agent->graphics_display_infos = g_hash_table_new_full(&g_direct_hash,
+ &g_direct_equal,
+ NULL,
+ &graphics_display_info_destroy);
+
return agent;
}
@@ -359,6 +427,7 @@ static void vdagent_destroy(VDAgent *agent)
g_clear_pointer(&agent->x11_channel, g_io_channel_unref);
g_clear_pointer(&agent->loop, g_main_loop_unref);
+ g_hash_table_destroy(agent->graphics_display_infos);
g_free(agent);
}
diff --git a/src/vdagentd-proto-strings.h b/src/vdagentd-proto-strings.h
index 6e7bcee..7e03f46 100644
--- a/src/vdagentd-proto-strings.h
+++ b/src/vdagentd-proto-strings.h
@@ -36,6 +36,7 @@ static const char * const vdagentd_messages[] = {
"file xfer data",
"file xfer disable",
"client disconnected",
+ "graphics device info",
};
#endif
diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h
index f72a890..243a9c6 100644
--- a/src/vdagentd-proto.h
+++ b/src/vdagentd-proto.h
@@ -44,6 +44,7 @@ enum {
VDAGENTD_FILE_XFER_DATA,
VDAGENTD_FILE_XFER_DISABLE,
VDAGENTD_CLIENT_DISCONNECTED, /* daemon -> client */
+ VDAGENTD_GRAPHICS_DEVICE_INFO, /* daemon -> client */
VDAGENTD_NO_MESSAGES /* Must always be last */
};
diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c
index 99683da..7c37358 100644
--- a/src/vdagentd/vdagentd.c
+++ b/src/vdagentd/vdagentd.c
@@ -375,6 +375,16 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport,
udscs_write(conn, msg_type, 0, 0, data, message_header->size);
}
+static void forward_data_to_session_agent(uint32_t type, uint8_t *data, size_t size)
+{
+ if (active_session_conn == NULL) {
+ syslog(LOG_DEBUG, "No active session, can't forward message (type %u)", type);
+ return;
+ }
+
+ udscs_write(active_session_conn, type, 0, 0, data, size);
+}
+
static gsize vdagent_message_min_size[] =
{
-1, /* Does not exist */
@@ -393,6 +403,7 @@ static gsize vdagent_message_min_size[] =
0, /* VD_AGENT_CLIENT_DISCONNECTED */
sizeof(VDAgentMaxClipboard), /* VD_AGENT_MAX_CLIPBOARD */
sizeof(VDAgentAudioVolumeSync), /* VD_AGENT_AUDIO_VOLUME_SYNC */
+ sizeof(VDAgentGraphicsDeviceInfo), /* VD_AGENT_GRAPHICS_DEVICE_INFO */
};
static void vdagent_message_clipboard_from_le(VDAgentMessage *message_header,
@@ -477,6 +488,7 @@ static gboolean vdagent_message_check_size(const VDAgentMessage *message_header)
case VD_AGENT_CLIPBOARD_GRAB:
case VD_AGENT_AUDIO_VOLUME_SYNC:
case VD_AGENT_ANNOUNCE_CAPABILITIES:
+ case VD_AGENT_GRAPHICS_DEVICE_INFO:
if (message_header->size < min_size) {
syslog(LOG_ERR, "read: invalid message size: %u for message type: %u",
message_header->size, message_header->type);
@@ -550,6 +562,10 @@ static int virtio_port_read_complete(
syslog(LOG_DEBUG, "Set max clipboard: %d", max_clipboard);
break;
}
+ case VD_AGENT_GRAPHICS_DEVICE_INFO: {
+ forward_data_to_session_agent(VDAGENTD_GRAPHICS_DEVICE_INFO, data, message_header->size);
+ break;
+ }
case VD_AGENT_AUDIO_VOLUME_SYNC: {
VDAgentAudioVolumeSync *vdata = (VDAgentAudioVolumeSync *)data;
virtio_msg_uint16_from_le((uint8_t *)vdata, message_header->size,
--
2.19.1
More information about the Spice-devel
mailing list