Acked-by: Jonathon Jongsma <jjong...@redhat.com>

On Mon, 2019-01-28 at 15:09 +0100, Lukáš Hrázký wrote:
> 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 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.

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

Reply via email to