[Spice-commits] 3 commits - server/main-dispatcher.c server/main-dispatcher.h server/reds.c server/reds.h server/tests

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Feb 12 22:35:15 UTC 2019


 server/main-dispatcher.c          |   29 +------
 server/main-dispatcher.h          |    2 
 server/reds.c                     |  145 ++++++++++++++++----------------------
 server/reds.h                     |    3 
 server/tests/test-stream-device.c |   70 ++++++++++++++++++
 5 files changed, 144 insertions(+), 105 deletions(-)

New commits:
commit a7a8487d0fc109906208b2ccde5f95ac807ca5e0
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sun Feb 10 21:39:21 2019 +0000

    Remove core parameter from main_dispatcher_new
    
    This was added in bd8771adbcf3ff34d14333cf874191e8d105f612.
    There's no reason to not use reds function instead.
    MainDispatcher needs to listen in the main thread that is the
    one provided by reds_core_* functions.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
index 99d2a621..82b25e6e 100644
--- a/server/main-dispatcher.c
+++ b/server/main-dispatcher.c
@@ -48,7 +48,6 @@
  */
 struct MainDispatcherPrivate
 {
-    SpiceCoreInterfaceInternal *core; /* weak */
     RedsState *reds; /* weak */
     SpiceWatch *watch;
 };
@@ -58,7 +57,6 @@ G_DEFINE_TYPE_WITH_PRIVATE(MainDispatcher, main_dispatcher, TYPE_DISPATCHER)
 enum {
     PROP0,
     PROP_SPICE_SERVER,
-    PROP_CORE_INTERFACE
 };
 
 static void
@@ -73,9 +71,6 @@ main_dispatcher_get_property(GObject    *object,
         case PROP_SPICE_SERVER:
              g_value_set_pointer(value, self->priv->reds);
             break;
-        case PROP_CORE_INTERFACE:
-             g_value_set_pointer(value, self->priv->core);
-            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
     }
@@ -93,9 +88,6 @@ main_dispatcher_set_property(GObject      *object,
         case PROP_SPICE_SERVER:
             self->priv->reds = g_value_get_pointer(value);
             break;
-        case PROP_CORE_INTERFACE:
-            self->priv->core = g_value_get_pointer(value);
-            break;
         default:
             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
     }
@@ -121,14 +113,6 @@ main_dispatcher_class_init(MainDispatcherClass *klass)
                                                          "The spice server associated with this dispatcher",
                                                          G_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT_ONLY));
-
-    g_object_class_install_property(object_class,
-                                    PROP_CORE_INTERFACE,
-                                    g_param_spec_pointer("core-interface",
-                                                         "core-interface",
-                                                         "The SpiceCoreInterface server associated with this dispatcher",
-                                                         G_PARAM_READWRITE |
-                                                         G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
@@ -284,11 +268,10 @@ static void dispatcher_handle_read(int fd, int event, void *opaque)
  * Reds routines shouldn't be exposed. Instead reds.c should register the callbacks,
  * and the corresponding operations should be made only via main_dispatcher.
  */
-MainDispatcher* main_dispatcher_new(RedsState *reds, SpiceCoreInterfaceInternal *core)
+MainDispatcher* main_dispatcher_new(RedsState *reds)
 {
     MainDispatcher *self = g_object_new(TYPE_MAIN_DISPATCHER,
                                         "spice-server", reds,
-                                        "core-interface", core,
                                         "max-message-type", MAIN_DISPATCHER_NUM_MESSAGES,
                                         NULL);
     return self;
@@ -302,10 +285,10 @@ void main_dispatcher_constructed(GObject *object)
     dispatcher_set_opaque(DISPATCHER(self), self);
 
     self->priv->watch =
-        self->priv->core->watch_add(self->priv->core,
-                                    dispatcher_get_recv_fd(DISPATCHER(self)),
-                                    SPICE_WATCH_EVENT_READ, dispatcher_handle_read,
-                                    DISPATCHER(self));
+        reds_core_watch_add(self->priv->reds,
+                            dispatcher_get_recv_fd(DISPATCHER(self)),
+                            SPICE_WATCH_EVENT_READ, dispatcher_handle_read,
+                            DISPATCHER(self));
     dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_CHANNEL_EVENT,
                                 main_dispatcher_handle_channel_event,
                                 sizeof(MainDispatcherChannelEventMessage), false);
@@ -324,7 +307,7 @@ static void main_dispatcher_finalize(GObject *object)
 {
     MainDispatcher *self = MAIN_DISPATCHER(object);
 
-    self->priv->core->watch_remove(self->priv->core, self->priv->watch);
+    reds_core_watch_remove(self->priv->reds, self->priv->watch);
     self->priv->watch = NULL;
     G_OBJECT_CLASS(main_dispatcher_parent_class)->finalize(object);
 }
diff --git a/server/main-dispatcher.h b/server/main-dispatcher.h
index 088a5c21..e1244f83 100644
--- a/server/main-dispatcher.h
+++ b/server/main-dispatcher.h
@@ -59,6 +59,6 @@ void main_dispatcher_set_mm_time_latency(MainDispatcher *self, RedClient *client
  */
 void main_dispatcher_client_disconnect(MainDispatcher *self, RedClient *client);
 
-MainDispatcher* main_dispatcher_new(RedsState *reds, SpiceCoreInterfaceInternal *core);
+MainDispatcher* main_dispatcher_new(RedsState *reds);
 
 #endif /* MAIN_DISPATCHER_H_ */
diff --git a/server/reds.c b/server/reds.c
index b7325394..306bb7c6 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3504,7 +3504,7 @@ static int do_spice_init(RedsState *reds, SpiceCoreInterface *core_interface)
     reds->agent_dev = red_char_device_vdi_port_new(reds);
     reds_update_agent_properties(reds);
     reds->clients = NULL;
-    reds->main_dispatcher = main_dispatcher_new(reds, &reds->core);
+    reds->main_dispatcher = main_dispatcher_new(reds);
     reds->channels = NULL;
     reds->mig_target_clients = NULL;
     reds->char_devices = NULL;
commit b9e24dba58b8fba1b3d5899a013e0fa2f4a52888
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sat Feb 2 12:07:30 2019 +0000

    test-stream-device: Check monitor ID messages
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/tests/test-stream-device.c b/server/tests/test-stream-device.c
index f1707d2f..e63952ac 100644
--- a/server/tests/test-stream-device.c
+++ b/server/tests/test-stream-device.c
@@ -491,6 +491,75 @@ static void test_stream_device_data_message(TestFixture *fixture, gconstpointer
     g_assert_cmpint(send_data_bytes, ==, 1017);
 }
 
+static void test_display_info(TestFixture *fixture, gconstpointer user_data)
+{
+    // initialize a QXL interface. This must be done before receiving the display info message from
+    // the stream
+    test_add_display_interface(test);
+    // qxl device supports 2 monitors
+    spice_qxl_set_device_info(&test->qxl_instance, "pci/0/1.2", 0, 2);
+
+    // craft a message from the mock stream device that provides display info to the server for the
+    // given stream
+    static const char address[] = "pci/a/b.cde";
+    StreamMsgDeviceDisplayInfo info = {
+        .stream_id = GUINT32_TO_LE(0x01020304),
+        .device_display_id = GUINT32_TO_LE(0x0a0b0c0d),
+        .device_address_len = GUINT32_TO_LE(sizeof(address)),
+    };
+    uint8_t *p = message;
+    p = add_stream_hdr(p, STREAM_TYPE_DEVICE_DISPLAY_INFO, sizeof(info) + sizeof(address));
+    memcpy(p, &info, sizeof(info));
+    p += sizeof(info);
+    strcpy((char*)p, address);
+    p += sizeof(address);
+
+    *message_sizes_end = p - message;
+    ++message_sizes_end;
+
+    // parse the simulated display info message from the stream device so the server now has display
+    // info for the mock stream device
+    test_kick();
+
+    // build the buffer to send to the agent for display information
+    SpiceMarshaller *m = spice_marshaller_new();
+    reds_marshall_device_display_info(test->server, m);
+    int to_free;
+    size_t buf_len;
+    uint8_t *buf = spice_marshaller_linearize(m, 0, &buf_len, &to_free);
+
+    // check output buffer. The message that we send to the vdagent should combine display info for
+    // the stream device that we crafted above and the qxl device.
+    static const uint8_t expected_buffer[] = {
+        /* device count */        3,  0,  0,  0,
+
+        /* channel_id */          0,  0,  0,  0,
+        /* monitor_id */          0,  0,  0,  0,
+        /* device_display_id */   0,  0,  0,  0,
+        /* device_address_len */ 10,  0,  0,  0,
+        /* device_address */    'p','c','i','/','0','/','1','.','2',  0,
+
+        /* channel_id */          0,  0,  0,  0,
+        /* monitor_id */          1,  0,  0,  0,
+        /* device_display_id */   1,  0,  0,  0,
+        /* device_address_len */ 10,  0,  0,  0,
+        /* device_address */    'p','c', 'i','/','0','/','1','.','2',  0,
+
+        /* channel_id */          1,  0,  0,  0,
+        /* monitor_id */          4,  3,  2,  1,
+        /* device_display_id */  13, 12, 11, 10,
+        /* device_address_len */ 12,  0,  0,  0,
+        /* device_address */    'p','c','i','/','a','/','b','.','c','d','e',  0
+    };
+    g_assert_cmpint(buf_len, ==, sizeof(expected_buffer));
+    g_assert_true(memcmp(buf, expected_buffer, buf_len) == 0);
+
+    if (to_free) {
+        free(buf);
+    }
+    spice_marshaller_destroy(m);
+}
+
 static void test_add(const char *name, void (*func)(TestFixture *, gconstpointer), gconstpointer arg)
 {
     g_test_add(name, TestFixture, arg, test_stream_device_setup, func, test_stream_device_teardown);
@@ -516,6 +585,7 @@ int main(int argc, char *argv[])
              test_stream_device_huge_data, NULL);
     test_add("/server/stream-device-data-message",
              test_stream_device_data_message, NULL);
+    test_add("/server/display-info", test_display_info, NULL);
 
     return g_test_run();
 }
commit 3838f5470bf3f1ec2ccb266ec5f20d0cfb8132a7
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Fri Feb 8 11:48:23 2019 +0000

    reds: Factor out a function to marshal VDAgentGraphicsDeviceInfo message
    
    Instead of scanning the monitor twice (one to compute the size
    and another to build the message) use a single function to
    marshal the message.
    This also fixes big endian machines (which are not supported).
    Marshal function is exported to make easier to test (see following
    patch).
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
    Acked-by: Jonathon Jongsma <jjongsma at redhat.com>

diff --git a/server/reds.c b/server/reds.c
index d0efeb78..b7325394 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -897,78 +897,33 @@ static RedPipeItem *vdi_port_read_one_msg_from_device(RedCharDevice *self,
     return NULL;
 }
 
-void reds_send_device_display_info(RedsState *reds)
+void reds_marshall_device_display_info(RedsState *reds, SpiceMarshaller *m)
 {
-    if (!reds->agent_dev->priv->agent_attached) {
-        return;
-    }
-    g_debug("Sending device display info to the agent:");
-
     QXLInstance *qxl;
     RedCharDevice *dev;
 
-    size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
-
-    // size for the qxl device info
-    FOREACH_QXL_INSTANCE(reds, qxl) {
-        message_size +=
-            (sizeof(VDAgentDeviceDisplayInfo) + strlen(red_qxl_get_device_address(qxl)) + 1) *
-            red_qxl_get_monitors_count(qxl);
-    }
-
-    // size for the stream device info
-    GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
-        if (IS_STREAM_DEVICE(dev)) {
-            size_t device_address_len =
-                strlen(stream_device_get_device_display_info(STREAM_DEVICE(dev))->device_address);
-
-            if (device_address_len == 0) {
-                // the device info wasn't set (yet), don't send it
-                continue;
-            }
-
-            message_size += (sizeof(VDAgentDeviceDisplayInfo) + device_address_len + 1);
-        }
-    }
-
-    RedCharDeviceWriteBuffer *char_dev_buf = vdagent_new_write_buffer(reds->agent_dev,
-                                         VD_AGENT_GRAPHICS_DEVICE_INFO,
-                                         message_size,
-                                         true);
-
-    if (!char_dev_buf) {
-        reds->pending_device_display_info_message = true;
-        return;
-    }
-
-    VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
-    VDAgentGraphicsDeviceInfo *graphics_device_info = &internal_buf->u.graphics_device_info;
-    graphics_device_info->count = 0;
-
-    VDAgentDeviceDisplayInfo *device_display_info = graphics_device_info->display_info;
+    uint32_t device_count = 0;
+    void *device_count_ptr = spice_marshaller_add_uint32(m, device_count);
 
     // add the qxl devices to the message
     FOREACH_QXL_INSTANCE(reds, qxl) {
+        const char *const device_address = red_qxl_get_device_address(qxl);
+        const size_t device_address_len = strlen(device_address) + 1;
+        if (device_address_len == 1) {
+            continue;
+        }
         for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i) {
-            device_display_info->channel_id = qxl->id;
-            device_display_info->monitor_id = i;
-            device_display_info->device_display_id = red_qxl_get_device_display_ids(qxl)[i];
-
-            strcpy((char*) device_display_info->device_address, red_qxl_get_device_address(qxl));
-
-            device_display_info->device_address_len =
-                strlen((char*) device_display_info->device_address) + 1;
-
-            g_debug("   (qxl)    channel_id: %u monitor_id: %u, device_address: %s, device_display_id: %u",
-                    device_display_info->channel_id,
-                    device_display_info->monitor_id,
-                    device_display_info->device_address,
-                    device_display_info->device_display_id);
-
-            device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) device_display_info +
-                    sizeof(VDAgentDeviceDisplayInfo) + device_display_info->device_address_len);
-
-            graphics_device_info->count++;
+            spice_marshaller_add_uint32(m, qxl->id);
+            spice_marshaller_add_uint32(m, i);
+            spice_marshaller_add_uint32(m, red_qxl_get_device_display_ids(qxl)[i]);
+            spice_marshaller_add_uint32(m, device_address_len);
+            spice_marshaller_add(m, (void*) device_address, device_address_len);
+            ++device_count;
+
+            g_debug("   (qxl)    channel_id: %u monitor_id: %zu, device_address: %s, "
+                    "device_display_id: %u",
+                    qxl->id, i, device_address,
+                    red_qxl_get_device_display_ids(qxl)[i]);
         }
     }
 
@@ -977,9 +932,9 @@ void reds_send_device_display_info(RedsState *reds)
         if (IS_STREAM_DEVICE(dev)) {
             StreamDevice *stream_dev = STREAM_DEVICE(dev);
             const StreamDeviceDisplayInfo *info = stream_device_get_device_display_info(stream_dev);
-            size_t device_address_len = strlen(info->device_address);
+            size_t device_address_len = strlen(info->device_address) + 1;
 
-            if (device_address_len == 0) {
+            if (device_address_len == 1) {
                 // the device info wasn't set (yet), don't send it
                 continue;
             }
@@ -990,25 +945,53 @@ void reds_send_device_display_info(RedsState *reds)
                 continue;
             }
 
-            device_display_info->channel_id = channel_id;
-            device_display_info->monitor_id = info->stream_id;
-            device_display_info->device_display_id = info->device_display_id;
+            spice_marshaller_add_uint32(m, channel_id);
+            spice_marshaller_add_uint32(m, info->stream_id);
+            spice_marshaller_add_uint32(m, info->device_display_id);
+            spice_marshaller_add_uint32(m, device_address_len);
+            spice_marshaller_add(m, (void*) info->device_address, device_address_len);
+            ++device_count;
+
+            g_debug("   (stream) channel_id: %u monitor_id: %u, device_address: %s, "
+                    "device_display_id: %u",
+                    channel_id, info->stream_id, info->device_address,
+                    info->device_display_id);
+        }
+    }
+    spice_marshaller_set_uint32(m, device_count_ptr, device_count);
+}
 
-            strcpy((char*) device_display_info->device_address, info->device_address);
-            device_display_info->device_address_len = device_address_len + 1;
+void reds_send_device_display_info(RedsState *reds)
+{
+    if (!reds->agent_dev->priv->agent_attached) {
+        return;
+    }
+    g_debug("Sending device display info to the agent:");
 
-            g_debug("   (stream) channel_id: %u monitor_id: %u, device_address: %s, device_display_id: %u",
-                    device_display_info->channel_id,
-                    device_display_info->monitor_id,
-                    device_display_info->device_address,
-                    device_display_info->device_display_id);
+    SpiceMarshaller *m = spice_marshaller_new();
+    reds_marshall_device_display_info(reds, m);
 
-            device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) device_display_info +
-                    sizeof(VDAgentDeviceDisplayInfo) + device_display_info->device_address_len);
+    RedCharDeviceWriteBuffer *char_dev_buf = vdagent_new_write_buffer(reds->agent_dev,
+                                         VD_AGENT_GRAPHICS_DEVICE_INFO,
+                                         spice_marshaller_get_total_size(m),
+                                         true);
 
-            graphics_device_info->count++;
-        }
+    if (!char_dev_buf) {
+        spice_marshaller_destroy(m);
+        reds->pending_device_display_info_message = true;
+        return;
+    }
+
+    VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+
+    int free_info;
+    size_t len_info;
+    uint8_t *info = spice_marshaller_linearize(m, 0, &len_info, &free_info);
+    memcpy(&internal_buf->u.graphics_device_info, info, len_info);
+    if (free_info) {
+        free(info);
     }
+    spice_marshaller_destroy(m);
 
     reds->pending_device_display_info_message = false;
 
diff --git a/server/reds.h b/server/reds.h
index e3641fa1..8c5ee84d 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -100,6 +100,9 @@ SpiceCoreInterfaceInternal* reds_get_core_interface(RedsState *reds);
 void reds_update_client_mouse_allowed(RedsState *reds);
 MainDispatcher* reds_get_main_dispatcher(RedsState *reds);
 
+/* Marshal VDAgentGraphicsDeviceInfo structure */
+void reds_marshall_device_display_info(RedsState *reds, SpiceMarshaller *m);
+
 /* Get the recording object stored in RedsState.
  * You should free with red_record_unref.
  */


More information about the Spice-commits mailing list