[Spice-devel] [RFC PATCH spice-server v5 04/22] stream-device: Start parsing new protocol from guest

Jonathon Jongsma jjongsma at redhat.com
Fri Sep 1 19:26:32 UTC 2017


Acked-by: Jonathon Jongsma <jjongsma at redhat.com>


On Wed, 2017-08-30 at 16:28 +0100, Frediano Ziglio wrote:
> Parse the data sent from the guest to the streaming device.
> At the moment, the data is simply discarded after it is parsed.
> 
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  server/stream-device.c | 128
> +++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 124 insertions(+), 4 deletions(-)
> 
> diff --git a/server/stream-device.c b/server/stream-device.c
> index f3a147b8..58edb3d1 100644
> --- a/server/stream-device.c
> +++ b/server/stream-device.c
> @@ -19,6 +19,8 @@
>  #include <config.h>
>  #endif
>  
> +#include <spice/stream-device.h>
> +
>  #include "char-device.h"
>  
>  #define TYPE_STREAM_DEVICE stream_device_get_type()
> @@ -35,6 +37,9 @@ typedef struct StreamDeviceClass StreamDeviceClass;
>  
>  struct StreamDevice {
>      RedCharDevice parent;
> +    StreamDevHeader hdr;
> +    uint8_t hdr_pos;
> +    bool has_error;
>  };
>  
>  struct StreamDeviceClass {
> @@ -46,21 +51,136 @@ static StreamDevice
> *stream_device_new(SpiceCharDeviceInstance *sin, RedsState *
>  
>  G_DEFINE_TYPE(StreamDevice, stream_device, RED_TYPE_CHAR_DEVICE)
>  
> +typedef bool StreamMsgHandler(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
> +    SPICE_GNUC_WARN_UNUSED_RESULT;
> +
> +static StreamMsgHandler handle_msg_format, handle_msg_data;
> +
> +static bool handle_msg_invalid(StreamDevice *dev,
> SpiceCharDeviceInstance *sin,
> +                               const char *error_msg)
> SPICE_GNUC_WARN_UNUSED_RESULT;
> +
>  static RedPipeItem *
>  stream_device_read_msg_from_dev(RedCharDevice *self,
> SpiceCharDeviceInstance *sin)
>  {
> +    StreamDevice *dev = STREAM_DEVICE(self);
>      SpiceCharDeviceInterface *sif;
>      int n;
> +    bool handled = false;
> +
> +    if (dev->has_error) {
> +        return NULL;
> +    }
>  
>      sif = spice_char_device_get_interface(sin);
>  
> -    do {
> -        uint8_t buf[256];
> +    /* read header */
> +    while (dev->hdr_pos < sizeof(dev->hdr)) {
> +        n = sif->read(sin, (uint8_t *) &dev->hdr, sizeof(dev->hdr) -
> dev->hdr_pos);
> +        if (n <= 0) {
> +            return NULL;
> +        }
> +        dev->hdr_pos += n;
> +        if (dev->hdr_pos >= sizeof(dev->hdr)) {
> +            dev->hdr.type = GUINT16_FROM_LE(dev->hdr.type);
> +            dev->hdr.size = GUINT32_FROM_LE(dev->hdr.size);
> +        }
> +    }
> +
> +    switch ((StreamMsgType) dev->hdr.type) {
> +    case STREAM_TYPE_FORMAT:
> +        if (dev->hdr.size != sizeof(StreamMsgFormat)) {
> +            handled = handle_msg_invalid(dev, sin, "Wrong size for
> StreamMsgFormat");
> +        } else {
> +            handled = handle_msg_format(dev, sin);
> +        }
> +        break;
> +    case STREAM_TYPE_DATA:
> +        handled = handle_msg_data(dev, sin);
> +        break;
> +    case STREAM_TYPE_CAPABILITIES:
> +        /* FIXME */
> +    default:
> +        handled = handle_msg_invalid(dev, sin, "Invalid message
> type");
> +        break;
> +    }
> +
> +    /* current message has been handled, so reset state and get
> ready to parse
> +     * the next message */
> +    if (handled) {
> +        dev->hdr_pos = 0;
> +    }
> +
> +    return NULL;
> +}
> +
> +static bool
> +handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
> const char *error_msg)
> +{
> +    static const char default_error_msg[] = "Protocol error";
> +
> +    if (!error_msg) {
> +        error_msg = default_error_msg;
> +    }
> +
> +    int msg_size = sizeof(StreamMsgNotifyError) + strlen(error_msg)
> + 1;
> +    int total_size = sizeof(StreamDevHeader) + msg_size;
> +
> +    RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
> +    RedCharDeviceWriteBuffer *buf =
> +        red_char_device_write_buffer_get_server_no_token(char_dev,
> total_size);
> +    buf->buf_used = total_size;
> +
> +    StreamDevHeader *const hdr = (StreamDevHeader *)buf->buf;
> +    hdr->protocol_version = STREAM_DEVICE_PROTOCOL;
> +    hdr->padding = 0;
> +    hdr->type = GUINT16_TO_LE(STREAM_TYPE_NOTIFY_ERROR);
> +    hdr->size = GUINT32_TO_LE(msg_size);
> +
> +    StreamMsgNotifyError *const error = (StreamMsgNotifyError
> *)(hdr+1);
> +    error->error_code = GUINT32_TO_LE(0);
> +    strcpy((char *) error->msg, error_msg);
> +
> +    red_char_device_write_buffer_add(char_dev, buf);
> +
> +    dev->has_error = true;
> +    return false;
> +}
> +
> +static bool
> +handle_msg_format(StreamDevice *dev, SpiceCharDeviceInstance *sin)
> +{
> +    StreamMsgFormat fmt;
> +    SpiceCharDeviceInterface *sif =
> spice_char_device_get_interface(sin);
> +    int n = sif->read(sin, (uint8_t *) &fmt, sizeof(fmt));
> +    if (n == 0) {
> +        return false;
> +    }
> +    if (n != sizeof(fmt)) {
> +        return handle_msg_invalid(dev, sin, NULL);
> +    }
> +    fmt.width = GUINT32_FROM_LE(fmt.width);
> +    fmt.height = GUINT32_FROM_LE(fmt.height);
> +
> +    return true;
> +}
> +
> +static bool
> +handle_msg_data(StreamDevice *dev, SpiceCharDeviceInstance *sin)
> +{
> +    SpiceCharDeviceInterface *sif =
> spice_char_device_get_interface(sin);
> +    int n;
> +    while (1) {
> +        uint8_t buf[16 * 1024];
>          n = sif->read(sin, buf, sizeof(buf));
> +        /* TODO */
>          spice_debug("read %d bytes from device", n);
> -    } while (n > 0);
> +        if (n <= 0) {
> +            break;
> +        }
> +        dev->hdr.size -= n;
> +    }
>  
> -    return NULL;
> +    return dev->hdr.size == 0;
>  }
>  
>  static void



More information about the Spice-devel mailing list