Blame SOURCES/0017-stream-device-Start-supporting-resetting-device-when.patch

ad1357
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ad1357
From: Frediano Ziglio <fziglio@redhat.com>
ad1357
Date: Wed, 25 Jan 2017 22:42:00 +0000
ad1357
Subject: [spice-server] stream-device: Start supporting resetting device when
ad1357
 close/open on guest
ad1357
ad1357
When guest close the device the host device has to be reset too.
ad1357
This make easier to restart the guest device which can happen in case
ad1357
of reboot, agent issues or if we want to update the agent.
ad1357
ad1357
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
ad1357
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
ad1357
---
ad1357
 server/stream-channel.c | 34 ++++++++++++++++++++++++++++++++++
ad1357
 server/stream-channel.h |  7 ++++++-
ad1357
 server/stream-device.c  | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
ad1357
 3 files changed, 89 insertions(+), 1 deletion(-)
ad1357
ad1357
diff --git a/server/stream-channel.c b/server/stream-channel.c
ad1357
index e89563b82..51b8badf9 100644
ad1357
--- a/server/stream-channel.c
ad1357
+++ b/server/stream-channel.c
ad1357
@@ -483,3 +483,37 @@ stream_channel_register_start_cb(StreamChannel *channel,
ad1357
     channel->start_cb = cb;
ad1357
     channel->start_opaque = opaque;
ad1357
 }
ad1357
+
ad1357
+void
ad1357
+stream_channel_reset(StreamChannel *channel)
ad1357
+{
ad1357
+    struct {
ad1357
+        StreamMsgStartStop base;
ad1357
+        uint8_t codecs_buffer[MAX_SUPPORTED_CODECS];
ad1357
+    } start_msg;
ad1357
+    StreamMsgStartStop *const start = &start_msg.base;
ad1357
+    RedChannel *red_channel = RED_CHANNEL(channel);
ad1357
+
ad1357
+    // send destroy old stream
ad1357
+    red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
ad1357
+
ad1357
+    // destroy display surface
ad1357
+    if (channel->width != 0 && channel->height != 0) {
ad1357
+        red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
ad1357
+    }
ad1357
+
ad1357
+    channel->stream_id = -1;
ad1357
+    channel->width = 0;
ad1357
+    channel->height = 0;
ad1357
+
ad1357
+    if (!red_channel_is_connected(red_channel)) {
ad1357
+        return;
ad1357
+    }
ad1357
+
ad1357
+    // try to request a new stream, this should start a new stream
ad1357
+    // if the guest is connected to the device and a client is already connected
ad1357
+    start->num_codecs = stream_channel_get_supported_codecs(channel, start->codecs);
ad1357
+    // send in any case, even if list is not changed
ad1357
+    // notify device about changes
ad1357
+    request_new_stream(channel, start);
ad1357
+}
ad1357
diff --git a/server/stream-channel.h b/server/stream-channel.h
ad1357
index ba098df49..bd075a951 100644
ad1357
--- a/server/stream-channel.h
ad1357
+++ b/server/stream-channel.h
ad1357
@@ -48,7 +48,12 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
ad1357
  */
ad1357
 StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
ad1357
 
ad1357
-struct StreamMsgFormat;
ad1357
+/**
ad1357
+ * Reset channel at initial state
ad1357
+ */
ad1357
+void stream_channel_reset(StreamChannel *channel);
ad1357
+
ad1357
+struct StreamMsgStreamFormat;
ad1357
 struct StreamMsgStartStop;
ad1357
 
ad1357
 void stream_channel_change_format(StreamChannel *channel,
ad1357
diff --git a/server/stream-device.c b/server/stream-device.c
ad1357
index 6e78b1a99..9e401f8ed 100644
ad1357
--- a/server/stream-device.c
ad1357
+++ b/server/stream-device.c
ad1357
@@ -43,6 +43,7 @@ struct StreamDevice {
ad1357
     StreamDevHeader hdr;
ad1357
     uint8_t hdr_pos;
ad1357
     bool has_error;
ad1357
+    bool opened;
ad1357
     StreamChannel *stream_channel;
ad1357
 };
ad1357
 
ad1357
@@ -203,6 +204,35 @@ stream_device_remove_client(RedCharDevice *self, RedClient *client)
ad1357
 {
ad1357
 }
ad1357
 
ad1357
+static void
ad1357
+stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
ad1357
+                           StreamChannel *stream_channel G_GNUC_UNUSED)
ad1357
+{
ad1357
+    StreamDevice *dev = (StreamDevice *) opaque;
ad1357
+
ad1357
+    if (!dev->opened) {
ad1357
+        return;
ad1357
+    }
ad1357
+
ad1357
+    int msg_size = sizeof(*start) + sizeof(start->codecs[0]) * start->num_codecs;
ad1357
+    int total_size = sizeof(StreamDevHeader) + msg_size;
ad1357
+
ad1357
+    RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
ad1357
+    RedCharDeviceWriteBuffer *buf =
ad1357
+        red_char_device_write_buffer_get_server_no_token(char_dev, total_size);
ad1357
+    buf->buf_used = total_size;
ad1357
+
ad1357
+    StreamDevHeader *hdr = (StreamDevHeader *)buf->buf;
ad1357
+    hdr->protocol_version = STREAM_DEVICE_PROTOCOL;
ad1357
+    hdr->padding = 0;
ad1357
+    hdr->type = GUINT16_TO_LE(STREAM_TYPE_START_STOP);
ad1357
+    hdr->size = GUINT32_TO_LE(msg_size);
ad1357
+
ad1357
+    memcpy(&hdr[1], start, msg_size);
ad1357
+
ad1357
+    red_char_device_write_buffer_add(char_dev, buf);
ad1357
+}
ad1357
+
ad1357
 RedCharDevice *
ad1357
 stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
ad1357
 {
ad1357
@@ -212,6 +242,7 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
ad1357
 
ad1357
     StreamDevice *dev = stream_device_new(sin, reds);
ad1357
     dev->stream_channel = stream_channel;
ad1357
+    stream_channel_register_start_cb(stream_channel, stream_device_stream_start, dev);
ad1357
 
ad1357
     sif = spice_char_device_get_interface(sin);
ad1357
     if (sif->state) {
ad1357
@@ -234,6 +265,23 @@ stream_device_dispose(GObject *object)
ad1357
 }
ad1357
 
ad1357
 static void
ad1357
+stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
ad1357
+{
ad1357
+    if (event != SPICE_PORT_EVENT_OPENED && event != SPICE_PORT_EVENT_CLOSED) {
ad1357
+        return;
ad1357
+    }
ad1357
+
ad1357
+    StreamDevice *dev = STREAM_DEVICE(char_dev);
ad1357
+
ad1357
+    // reset device and channel on close/open
ad1357
+    dev->opened = (event == SPICE_PORT_EVENT_OPENED);
ad1357
+    dev->hdr_pos = 0;
ad1357
+    dev->has_error = false;
ad1357
+    red_char_device_reset(char_dev);
ad1357
+    stream_channel_reset(dev->stream_channel);
ad1357
+}
ad1357
+
ad1357
+static void
ad1357
 stream_device_class_init(StreamDeviceClass *klass)
ad1357
 {
ad1357
     GObjectClass *object_class = G_OBJECT_CLASS(klass);
ad1357
@@ -245,6 +293,7 @@ stream_device_class_init(StreamDeviceClass *klass)
ad1357
     char_dev_class->send_msg_to_client = stream_device_send_msg_to_client;
ad1357
     char_dev_class->send_tokens_to_client = stream_device_send_tokens_to_client;
ad1357
     char_dev_class->remove_client = stream_device_remove_client;
ad1357
+    char_dev_class->port_event = stream_device_port_event;
ad1357
 }
ad1357
 
ad1357
 static void