[Spice-devel] [PATCH 4/7] server/red_dispatcher: client_monitors_config support

Alon Levy alevy at redhat.com
Mon Sep 10 08:43:59 PDT 2012


Adds two functions:
 red_dispatcher_use_client_monitors_config:
  - checks the guest for the QXL_GUEST_CAP_CLIENT_MONITORS_CONFIG_ISR
    cap, and that QXLInterface is new enough to support cap checking
    and client_monitors_config callback, returns TRUE if so.
  - red_dispatcher_client_monitors_config:
    send the client monitors configuration to the guest.

main_channel function added to avoid exposing MainChannelClient out of
main_channel.c
---
 server/main_channel.c   |  7 +++++
 server/main_channel.h   |  2 ++
 server/red_dispatcher.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 server/red_dispatcher.h |  5 ++++
 4 files changed, 88 insertions(+)

diff --git a/server/main_channel.c b/server/main_channel.c
index 0fd5ab6..37ed423 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -46,6 +46,7 @@
 #include "red_common.h"
 #include "reds.h"
 #include "migration_protocol.h"
+#include "red_dispatcher.h"
 
 #define ZERO_BUF_SIZE 4096
 
@@ -1335,3 +1336,9 @@ int main_channel_migrate_src_complete(MainChannel *main_chan, int success)
    }
    return semi_seamless_count;
 }
+
+void main_channel_client_client_monitors_config(MainChannelClient *mcc,
+                                                VDAgentMonitorsConfig *monitors_config)
+{
+    red_dispatcher_client_monitors_config(&mcc->base, monitors_config);
+}
diff --git a/server/main_channel.h b/server/main_channel.h
index 285a009..4ea907a 100644
--- a/server/main_channel.h
+++ b/server/main_channel.h
@@ -86,5 +86,7 @@ int main_channel_migrate_src_complete(MainChannel *main_chan, int success);
 void main_channel_migrate_dst_complete(MainChannelClient *mcc);
 void main_channel_push_name(MainChannelClient *mcc, const char *name);
 void main_channel_push_uuid(MainChannelClient *mcc, const uint8_t uuid[16]);
+void main_channel_client_client_monitors_config(MainChannelClient *mcc,
+                                                VDAgentMonitorsConfig *monitors_config);
 
 #endif
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 8e44674..2495efe 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -85,6 +85,41 @@ extern spice_wan_compression_t zlib_glz_state;
 
 static RedDispatcher *dispatchers = NULL;
 
+static int red_dispatcher_version_check(int major, int minor)
+{
+    if (num_active_workers > 0) {
+        RedDispatcher *now = dispatchers;
+        while (now) {
+            if (now->base.major_version != major ||
+                now->base.minor_version < minor) {
+                return FALSE;
+            }
+            now = now->next;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static int red_dispatcher_test_guest_cap(unsigned cap)
+{
+    RedDispatcher *now = dispatchers;
+    unsigned ind = cap / 8;
+    unsigned cap_mask = 1 << (cap & 7);
+
+    if (num_active_workers == 0) {
+        return FALSE;
+    }
+
+    for (; now; now = now->next) {
+        if (now->guest_capabilities_size < ind + 1 ||
+            !(now->guest_capabilities[ind] & cap_mask)) {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
 static void red_dispatcher_set_display_peer(RedChannel *channel, RedClient *client,
                                             RedsStream *stream, int migration,
                                             int num_common_caps, uint32_t *common_caps, int num_caps,
@@ -297,6 +332,45 @@ static void red_dispatcher_update_area(RedDispatcher *dispatcher, uint32_t surfa
                             &payload);
 }
 
+int red_dispatcher_use_client_monitors_config(void)
+{
+    RedDispatcher *now = dispatchers;
+
+    if (num_active_workers == 0) {
+        return FALSE;
+    }
+
+    for (; now ; now = now->next) {
+        if (!red_dispatcher_version_check(3, 2) ||
+            !now->qxl->st->qif->client_monitors_config ||
+            !red_dispatcher_test_guest_cap(QXL_GUEST_CAP_CLIENT_MONITORS_CONFIG_ISR)) {
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+void red_dispatcher_client_monitors_config(RedChannelClient *rcc,
+                                           VDAgentMonitorsConfig *monitors_config)
+{
+    RedDispatcher *now = dispatchers;
+
+    if (!rcc->channel) {
+        return;
+    }
+
+    while (now) {
+        if (now->qxl->st->qif->client_monitors_config) {
+            now->qxl->st->qif->client_monitors_config(now->qxl,
+                                                      monitors_config);
+        } else {
+            spice_warning("spice bug: red_dispatcher_client_monitors_config called\n"
+                          "with QXLInterface missing client_monitors_config callback\n");
+        }
+        now = now->next;
+    }
+}
+
 static AsyncCommand *async_command_alloc(RedDispatcher *dispatcher,
                                          RedWorkerMessage message,
                                          uint64_t cookie)
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index 7e9ffe6..ccab323 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -18,6 +18,8 @@
 #ifndef _H_RED_DISPATCHER
 #define _H_RED_DISPATCHER
 
+#include "red_channel.h"
+
 struct RedChannelClient;
 typedef struct AsyncCommand AsyncCommand;
 
@@ -35,6 +37,9 @@ uint32_t red_dispatcher_qxl_ram_size(void);
 int red_dispatcher_qxl_count(void);
 void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *);
 struct Dispatcher *red_dispatcher_get_dispatcher(struct RedDispatcher *);
+int red_dispatcher_use_client_monitors_config(void);
+void red_dispatcher_client_monitors_config(RedChannelClient *rcc,
+                                           VDAgentMonitorsConfig *monitors_config);
 
 typedef struct RedWorkerMessageDisplayConnect {
     RedClient * client;
-- 
1.7.12



More information about the Spice-devel mailing list