|
|
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
|