[Spice-devel] [RFC PATCH spice v2 09/20] reds: Add the monitors_guest_output_id hash table

Lukáš Hrázký lhrazky at redhat.com
Thu Aug 16 16:26:38 UTC 2018


A hash table of (channel_id, monitor_id) -> (guest_output_id) that
is meant to store the guest_output_ids of the streamed channels'
monitors.

Signed-off-by: Lukáš Hrázký <lhrazky at redhat.com>
---
 server/reds-private.h |  6 +++++
 server/reds.c         | 61 +++++++++++++++++++++++++++++++++++++++++++
 server/reds.h         |  5 ++++
 3 files changed, 72 insertions(+)

diff --git a/server/reds-private.h b/server/reds-private.h
index 920edc5c..a4828fec 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -123,6 +123,12 @@ struct RedsState {
      * client, being passed to the guest */
     SpiceBuffer client_monitors_config;
 
+    /* A map of (channel_id, monitor_id) -> guest_output_id. (channel_id,
+     * monitor_id) is a unique identifier of a monitor. However, that ID has no
+     * meaning in the guest context. for cases the guest monitor ID (called
+     * output ID) is available, it is stored in this hash table.
+     */
+    GHashTable *monitors_guest_output_id;
     int mm_time_enabled;
     uint32_t mm_time_latency;
 
diff --git a/server/reds.c b/server/reds.c
index 85043a88..d4356807 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -262,6 +262,11 @@ typedef struct __attribute__ ((__packed__)) VDInternalBuf {
     u;
 } VDInternalBuf;
 
+typedef struct MonitorKey {
+    uint32_t channel_id;
+    uint32_t monitor_id;
+} MonitorKey;
+
 SPICE_DECLARE_TYPE(RedCharDeviceVDIPort, red_char_device_vdi_port, CHAR_DEVICE_VDIPORT);
 #define RED_TYPE_CHAR_DEVICE_VDIPORT red_char_device_vdi_port_get_type()
 
@@ -621,6 +626,36 @@ bool reds_config_get_playback_compression(RedsState *reds)
     return reds->config->playback_compression;
 }
 
+void reds_store_monitor_guest_output_id(RedsState *reds, uint32_t channel_id,
+                                        uint32_t monitor_id, uint32_t guest_output_id)
+{
+    MonitorKey *key = g_malloc(sizeof(MonitorKey));
+
+    key->channel_id = channel_id;
+    key->monitor_id = monitor_id;
+
+    g_hash_table_insert(reds->monitors_guest_output_id, key, GUINT_TO_POINTER(guest_output_id));
+}
+
+bool reds_get_monitor_guest_output_id(RedsState *reds, uint32_t channel_id,
+                                      uint32_t monitor_id, uint32_t *guest_output_id)
+{
+    MonitorKey key = {
+        .channel_id = channel_id,
+        .monitor_id = monitor_id
+    };
+
+    gpointer value;
+    gboolean has_key = g_hash_table_lookup_extended(reds->monitors_guest_output_id, &key, NULL, &value);
+
+    if (!has_key) {
+        return FALSE;
+    }
+
+    *guest_output_id = GPOINTER_TO_INT(value);
+    return TRUE;
+}
+
 SpiceMouseMode reds_get_mouse_mode(RedsState *reds)
 {
     return reds->mouse_mode;
@@ -3354,6 +3389,24 @@ SPICE_GNUC_VISIBLE int spice_server_remove_interface(SpiceBaseInstance *sin)
     return 0;
 }
 
+static guint monitor_key_hash(gconstpointer key)
+{
+    const MonitorKey *monitor_key = (const MonitorKey*) key;
+    return g_int_hash(&monitor_key->channel_id) ^ g_int_hash(&monitor_key->monitor_id);
+}
+
+static gboolean monitor_key_equal(gconstpointer a, gconstpointer b)
+{
+    const MonitorKey *mka = (const MonitorKey*) a;
+    const MonitorKey *mkb = (const MonitorKey*) b;
+    return mka->channel_id == mkb->channel_id && mka->monitor_id == mkb->monitor_id;
+}
+
+static void monitor_key_destroy(gpointer key)
+{
+    g_free(key);
+}
+
 static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface)
 {
     spice_debug("starting %s", VERSION);
@@ -3404,6 +3457,11 @@ static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface)
 
     spice_buffer_free(&reds->client_monitors_config);
 
+    reds->monitors_guest_output_id = g_hash_table_new_full(&monitor_key_hash,
+                                                           &monitor_key_equal,
+                                                           &monitor_key_destroy,
+                                                           NULL);
+
     reds->allow_multiple_clients = getenv(SPICE_DEBUG_ALLOW_MC_ENV) != NULL;
     if (reds->allow_multiple_clients) {
         spice_warning("spice: allowing multiple client connections");
@@ -3697,6 +3755,9 @@ SPICE_GNUC_VISIBLE void spice_server_destroy(SpiceServer *reds)
     reds->channels = NULL;
 
     spice_buffer_free(&reds->client_monitors_config);
+
+    g_hash_table_destroy(reds->monitors_guest_output_id);
+
     red_record_unref(reds->record);
     reds_cleanup(reds);
 #ifdef RED_STATISTICS
diff --git a/server/reds.h b/server/reds.h
index 9f17a5ec..1f10c4b3 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -50,6 +50,11 @@ gboolean reds_config_get_agent_mouse(const RedsState *reds); // used by inputs_c
 int reds_has_vdagent(RedsState *reds); // used by inputs channel
 bool reds_config_get_playback_compression(RedsState *reds); // used by playback channel
 
+void reds_store_monitor_guest_output_id(RedsState *reds, uint32_t channel_id,
+                                        uint32_t monitor_id, uint32_t guest_output_id);
+bool reds_get_monitor_guest_output_id(RedsState *reds, uint32_t channel_id,
+                                      uint32_t monitor_id, uint32_t *guest_output_id);
+
 void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState *mouse_state); // used by inputs_channel
 
 GArray* reds_get_renderers(RedsState *reds);
-- 
2.18.0



More information about the Spice-devel mailing list