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ý <lhrazky@xxxxxxxxxx> --- 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 7f8ac35d..37f3d9c8 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 3b553510..38df8e4c 100644 --- a/server/red-stream-device.c +++ b/server/red-stream-device.c @@ -39,6 +39,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; @@ -51,6 +52,7 @@ struct StreamDevice { CursorChannel *cursor_channel; SpiceTimer *close_timer; uint32_t frame_mmtime; + StreamDeviceDisplayInfo device_display_info; }; struct StreamDeviceClass { @@ -66,8 +68,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; @@ -150,6 +152,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"); @@ -275,6 +284,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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel