Receives the GraphicsDeviceInfo message from the streaming agent and
stores the data in a list on the streaming device.

Signed-off-by: Lukáš Hrázký <lhra...@redhat.com>
---
 server/display-limits.h    |  3 ++
 server/red-qxl.c           |  2 +-
 server/red-stream-device.c | 78 +++++++++++++++++++++++++++++++++++++-
 server/red-stream-device.h |  8 ++++
 4 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/server/display-limits.h b/server/display-limits.h
index e875149b..d79d3211 100644
--- a/server/display-limits.h
+++ b/server/display-limits.h
@@ -25,4 +25,7 @@
 /** Maximum number of streams created by spice-server */
 #define NUM_STREAMS 50
 
+/** Maximum length of the device address string */
+#define MAX_DEVICE_ADDRESS_LEN 256
+
 #endif /* DISPLAY_LIMITS_H_ */
diff --git a/server/red-qxl.c b/server/red-qxl.c
index a56d9a52..943ccb08 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -37,11 +37,11 @@
 #include "dispatcher.h"
 #include "red-parse-qxl.h"
 #include "red-channel-client.h"
+#include "display-limits.h"
 
 #include "red-qxl.h"
 
 
-#define MAX_DEVICE_ADDRESS_LEN 256
 #define MAX_MONITORS_COUNT 16
 
 struct QXLState {
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 215ddbe7..6c90d77d 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -37,6 +37,7 @@ struct StreamDevice {
         StreamMsgCapabilities capabilities;
         StreamMsgCursorSet cursor_set;
         StreamMsgCursorMove cursor_move;
+        StreamMsgDeviceDisplayInfo device_display_info;
         uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
     } *msg;
     uint32_t msg_pos;
@@ -49,6 +50,7 @@ struct StreamDevice {
     CursorChannel *cursor_channel;
     SpiceTimer *close_timer;
     uint32_t frame_mmtime;
+    StreamDeviceDisplayInfo device_display_info;
 };
 
 struct StreamDeviceClass {
@@ -64,8 +66,8 @@ static void char_device_set_state(RedCharDevice *char_dev, 
int state);
 typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin)
     SPICE_GNUC_WARN_UNUSED_RESULT;
 
-static StreamMsgHandler handle_msg_format, handle_msg_data, 
handle_msg_cursor_set,
-    handle_msg_cursor_move, handle_msg_capabilities;
+static StreamMsgHandler handle_msg_format, handle_msg_device_display_info, 
handle_msg_data,
+    handle_msg_cursor_set, handle_msg_cursor_move, handle_msg_capabilities;
 
 static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
                                const char *error_msg) 
SPICE_GNUC_WARN_UNUSED_RESULT;
@@ -146,6 +148,13 @@ stream_device_partial_read(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
             handled = handle_msg_format(dev, sin);
         }
         break;
+    case STREAM_TYPE_DEVICE_DISPLAY_INFO:
+        if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) + 
MAX_DEVICE_ADDRESS_LEN) {
+            handled = handle_msg_invalid(dev, sin, "StreamMsgDeviceDisplayInfo 
too large");
+        } else {
+            handled = handle_msg_device_display_info(dev, sin);
+        }
+        break;
     case STREAM_TYPE_DATA:
         if (dev->hdr.size > 32*1024*1024) {
             handled = handle_msg_invalid(dev, sin, "STREAM_DATA too large");
@@ -271,6 +280,71 @@ handle_msg_format(StreamDevice *dev, 
SpiceCharDeviceInstance *sin)
     return true;
 }
 
+static bool
+handle_msg_device_display_info(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+{
+    SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
+
+    if (spice_extra_checks) {
+        spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
+        spice_assert(dev->hdr.type == STREAM_TYPE_DEVICE_DISPLAY_INFO);
+    }
+
+    if (dev->msg_len < dev->hdr.size) {
+        dev->msg = g_realloc(dev->msg, dev->hdr.size);
+        dev->msg_len = dev->hdr.size;
+    }
+
+    /* read from device */
+    ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev->hdr.size - 
dev->msg_pos);
+    if (n <= 0) {
+        return dev->msg_pos == dev->hdr.size;
+    }
+
+    dev->msg_pos += n;
+    if (dev->msg_pos != dev->hdr.size) { /* some bytes are still missing */
+        return false;
+    }
+
+    StreamMsgDeviceDisplayInfo *display_info_msg = 
&dev->msg->device_display_info;
+
+    size_t device_address_len = 
GUINT32_FROM_LE(display_info_msg->device_address_len);
+    if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
+        g_warning("Received a device address longer than %u (%zu), "
+                  "will be truncated!", MAX_DEVICE_ADDRESS_LEN, 
device_address_len);
+        device_address_len = sizeof(dev->device_display_info.device_address);
+    }
+
+    if (device_address_len == 0) {
+        g_warning("Zero length device_address in  DeviceDisplayInfo message, 
ignoring.");
+        return true;
+    }
+
+    if (display_info_msg->device_address + device_address_len > (uint8_t*) 
dev->msg + dev->hdr.size) {
+        g_warning("Malformed DeviceDisplayInfo message, device_address length 
(%zu) "
+                  "goes beyond the end of the message, ignoring.", 
device_address_len);
+        return true;
+    }
+
+    strncpy(dev->device_display_info.device_address,
+            (char*) display_info_msg->device_address,
+            device_address_len);
+
+    // make sure the string is terminated
+    dev->device_display_info.device_address[device_address_len - 1] = '\0';
+
+    dev->device_display_info.stream_id = 
GUINT32_FROM_LE(display_info_msg->stream_id);
+    dev->device_display_info.device_display_id = 
GUINT32_FROM_LE(display_info_msg->device_display_id);
+
+    g_debug("Received DeviceDisplayInfo from the streaming agent: stream_id 
%u, "
+            "device_address %s, device_display_id %u",
+            dev->device_display_info.stream_id,
+            dev->device_display_info.device_address,
+            dev->device_display_info.device_display_id);
+
+    return true;
+}
+
 static bool
 handle_msg_capabilities(StreamDevice *dev, SpiceCharDeviceInstance *sin)
 {
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index f0a5b5c1..996be016 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -19,6 +19,7 @@
 #ifndef STREAM_DEVICE_H
 #define STREAM_DEVICE_H
 
+#include "display-limits.h"
 #include "char-device.h"
 
 G_BEGIN_DECLS
@@ -41,6 +42,13 @@ typedef struct StreamDeviceClass StreamDeviceClass;
     (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_DEVICE, StreamDeviceClass))
 
 GType stream_device_get_type(void) G_GNUC_CONST;
+
+typedef struct StreamDeviceDisplayInfo {
+    uint32_t stream_id;
+    char device_address[MAX_DEVICE_ADDRESS_LEN];
+    uint32_t device_display_id;
+} StreamDeviceDisplayInfo;
+
 StreamDevice *stream_device_connect(RedsState *reds, SpiceCharDeviceInstance 
*sin);
 
 /* Create channel for the streaming device.
-- 
2.20.1

_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to