[Spice-devel] [PATCH vd_agent v4 6/6] Receive the graphics_device_info message

Lukáš Hrázký lhrazky at redhat.com
Mon Jan 28 14:09:14 UTC 2019


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>
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 configure.ac                 |  2 +-
 src/vdagent/vdagent.c        |  3 ++
 src/vdagent/x11-priv.h       |  1 +
 src/vdagent/x11-randr.c      | 65 ++++++++++++++++++++++++++++++++++++
 src/vdagent/x11.c            | 13 ++++++++
 src/vdagent/x11.h            |  1 +
 src/vdagentd-proto-strings.h |  1 +
 src/vdagentd-proto.h         |  1 +
 src/vdagentd/vdagentd.c      | 16 +++++++++
 9 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 7cb44db..7faebfd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,7 +102,7 @@ AC_ARG_ENABLE([static-uinput],
 
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.34])
 PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
-PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
+PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.16])
 PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
 PKG_CHECK_MODULES([DBUS], [dbus-1])
 
diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index 90247f9..7cc6287 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -240,6 +240,9 @@ static void daemon_read_complete(struct udscs_connection **connp,
                                               ((VDAgentFileXferDataMessage *)data)->id);
         }
         break;
+    case VDAGENTD_GRAPHICS_DEVICE_INFO:
+        vdagent_x11_handle_graphics_device_info(agent->x11, data, header->size);
+        break;
     case VDAGENTD_CLIENT_DISCONNECTED:
         vdagent_clipboards_release_all(agent->clipboards);
         if (vdagent_finalize_file_xfer(agent)) {
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
     int xrandr_minor;
     int has_xinerama;
     int dont_send_guest_xorg_res;
+    GHashTable *graphics_display_infos;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 192b888..405fca9 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -727,6 +727,71 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
     }
 }
 
+typedef struct GraphicsDisplayInfo {
+    char device_address[256];
+    uint32_t device_display_id;
+} GraphicsDisplayInfo;
+
+// handle the device info message from the server. This will allow us to
+// maintain a mapping from spice display id to xrandr output
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t *data, size_t size)
+{
+    VDAgentGraphicsDeviceInfo *graphics_device_info = (VDAgentGraphicsDeviceInfo *)data;
+    VDAgentDeviceDisplayInfo *device_display_info = graphics_device_info->display_info;
+
+    void *buffer_end = data + size;
+
+    syslog(LOG_INFO, "Received Graphics Device Info:");
+
+    for (size_t i = 0; i < graphics_device_info->count; ++i) {
+        if ((void*) device_display_info > buffer_end ||
+                (void*) (&device_display_info->device_address +
+                    device_display_info->device_address_len) > buffer_end) {
+            syslog(LOG_ERR, "Malformed graphics_display_info message, "
+                   "extends beyond the end of the buffer");
+            break;
+        }
+
+        GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
+        value->device_address[0] = '\0';
+
+        size_t device_address_len = device_display_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*) device_display_info->device_address,
+                device_address_len);
+
+        if (device_address_len > 0) {
+            value->device_address[device_address_len - 1] = '\0';  // make sure the string is terminated
+        } else {
+            syslog(LOG_WARNING, "Zero length device_address received for channel_id: %u, monitor_id: %u",
+                   device_display_info->channel_id, device_display_info->monitor_id);
+        }
+
+        value->device_display_id = device_display_info->device_display_id;
+
+        syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, "
+               "device_display_id: %u",
+               device_display_info->channel_id,
+               device_display_info->monitor_id,
+               value->device_address,
+               value->device_display_id);
+
+        g_hash_table_insert(x11->graphics_display_infos,
+                GUINT_TO_POINTER(device_display_info->channel_id + device_display_info->monitor_id),
+                value);
+
+        device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) device_display_info +
+            sizeof(VDAgentDeviceDisplayInfo) + device_display_info->device_address_len);
+    }
+}
+
+
 /*
  * Set monitor configuration according to client request.
  *
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 02b4858..ab822f8 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -196,6 +196,12 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
 #endif
 }
 
+static void graphics_display_info_destroy(gpointer gdi)
+{
+    g_free(gdi);
+}
+
+
 struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
     int debug, int sync)
 {
@@ -316,6 +322,12 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
                __func__, net_wm_name, vdagent_x11_has_icons_on_desktop(x11));
     g_free(net_wm_name);
 
+    x11->graphics_display_infos = g_hash_table_new_full(&g_direct_hash,
+                                                  &g_direct_equal,
+                                                  NULL,
+                                                  &graphics_display_info_destroy);
+
+
     /* Flush output buffers and consume any pending events */
     vdagent_x11_do_read(x11);
 
@@ -337,6 +349,7 @@ void vdagent_x11_destroy(struct vdagent_x11 *x11, int vdagentd_disconnected)
     }
 #endif
 
+    g_hash_table_destroy(x11->graphics_display_infos);
     XCloseDisplay(x11->display);
     g_free(x11->randr.failed_conf);
     g_free(x11);
diff --git a/src/vdagent/x11.h b/src/vdagent/x11.h
index 2117abf..bb2ac80 100644
--- a/src/vdagent/x11.h
+++ b/src/vdagent/x11.h
@@ -51,5 +51,6 @@ void vdagent_x11_client_disconnected(struct vdagent_x11 *x11);
 #endif
 
 int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
+void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t *data, size_t size);
 
 #endif
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 197f325..0bc2689 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 d0f771a..ec8defc 100644
--- a/src/vdagentd/vdagentd.c
+++ b/src/vdagentd/vdagentd.c
@@ -373,6 +373,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 */
@@ -391,6 +401,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,
@@ -475,6 +486,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);
@@ -548,6 +560,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.20.1



More information about the Spice-devel mailing list