[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