[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