[Spice-devel] [RFC PATCH spice-server v4 04/22] stream-device: Start parsing new protocol from guest
Jonathon Jongsma
jjongsma at redhat.com
Fri Aug 25 19:24:29 UTC 2017
On Fri, 2017-08-25 at 10:53 +0100, Frediano Ziglio wrote:
> Parse the data sent from the guest to the streaming device.
For completeness perhaps add "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 | 115
> ++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 110 insertions(+), 5 deletions(-)
>
> diff --git a/server/stream-device.c b/server/stream-device.c
> index f3a147b8..e343f1f5 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,24 +51,124 @@ static StreamDevice
> *stream_device_new(SpiceCharDeviceInstance *sin, RedsState *
>
> G_DEFINE_TYPE(StreamDevice, stream_device, RED_TYPE_CHAR_DEVICE)
>
> +typedef void StreamMsgHandler(StreamDevice *dev,
> SpiceCharDeviceInstance *sin);
> +
> +static StreamMsgHandler handle_msg_format, handle_msg_data,
> handle_msg_invalid;
> +
> static RedPipeItem *
> stream_device_read_msg_from_dev(RedCharDevice *self,
> SpiceCharDeviceInstance *sin)
> {
> + StreamDevice *dev = STREAM_DEVICE(self);
> SpiceCharDeviceInterface *sif;
> int n;
>
> + if (dev->has_error) {
> + return NULL;
> + }
> +
> sif = spice_char_device_get_interface(sin);
>
> - do {
> - uint8_t buf[256];
> - n = sif->read(sin, buf, sizeof(buf));
> - spice_debug("read %d bytes from device", n);
> - } while (n > 0);
> + /* 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)) {
> + handle_msg_invalid(dev, sin);
> + } else {
> + handle_msg_format(dev, sin);
> + }
> + break;
> + case STREAM_TYPE_DATA:
> + handle_msg_data(dev, sin);
> + break;
> + case STREAM_TYPE_CAPABILITIES:
> + /* FIXME */
> + default:
> + handle_msg_invalid(dev, sin);
> + break;
> + }
>
> return NULL;
> }
>
> static void
> +handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin)
> +{
> + static const char error_msg[] = "Wrong protocol";
Perhaps "Protocol error" would be more accurate than "Wrong protocol"?
Alternately, we could add a third const char* argument so that teh
calling function can customize the error message? (e.g. "Invalid
message type", "Wrong size for StreamMsgFormat", etc.)
> +
> + 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;
> +}
> +
> +static void
> +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;
> + }
> + if (n != sizeof(fmt)) {
> + handle_msg_invalid(dev, sin);
> + return;
> + }
> + fmt.width = GUINT32_FROM_LE(fmt.width);
> + fmt.height = GUINT32_FROM_LE(fmt.height);
> + dev->hdr_pos = 0;
> +}
> +
> +static void
> +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);
> + if (n <= 0) {
> + break;
> + }
> + dev->hdr.size -= n;
> + }
> + if (dev->hdr.size == 0) {
> + dev->hdr_pos = 0;
> + }
> +}
> +
> +static void
> stream_device_send_msg_to_client(RedCharDevice *self, RedPipeItem
> *msg, RedClient *client)
> {
> }
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
More information about the Spice-devel
mailing list