[Spice-devel] [RFC PATCH spice-server v4 15/22] stream-device: Start supporting resetting device when close/open on guest

Jonathon Jongsma jjongsma at redhat.com
Fri Aug 25 19:54:19 UTC 2017


On Fri, 2017-08-25 at 10:54 +0100, Frediano Ziglio wrote:
> When guest close the device the host device has to be reset too.
> This make easier to restart the guest device which can happen in case
> of reboot, agent issues or if we want to update the agent.
> 
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
>  server/stream-channel.c | 30 ++++++++++++++++++++++++++++++
>  server/stream-channel.h |  7 ++++++-
>  server/stream-device.c  | 49
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 85 insertions(+), 1 deletion(-)
> 
> diff --git a/server/stream-channel.c b/server/stream-channel.c
> index 6a6536aa..53a06f91 100644
> --- a/server/stream-channel.c
> +++ b/server/stream-channel.c
> @@ -483,3 +483,33 @@ stream_channel_register_start_cb(StreamChannel
> *channel,
>      channel->start_cb = cb;
>      channel->start_opaque = opaque;
>  }
> +
> +void
> +stream_channel_reset(StreamChannel *channel)
> +{
> +    RedChannel *red_channel = RED_CHANNEL(channel);
> +
> +    // send destroy old stream
> +    red_channel_pipes_add_type(red_channel,
> RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
> +
> +    // destroy display surface
> +    if (channel->width != 0 && channel->height != 0) {
> +        red_channel_pipes_add_type(red_channel,
> RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
> +    }
> +
> +    channel->stream_id = -1;
> +    channel->width = 0;
> +    channel->height = 0;
> +
> +    if (!red_channel_is_connected(red_channel)) {
> +        return;
> +    }
> +
> +    // try to ask new stream, this should start a new stream

"ask" -> "request a"

> +    // if the guest connect to the device and a client is already 

"if the guest is connected"

> connected
> +    StreamMsgStartStop* start =
> stream_channel_get_supported_codecs(channel);
> +    // send in any case, even if list is not changed
> +    // notify device about changes
> +    request_new_stream(channel, start);
> +    free(start);
> +}
> diff --git a/server/stream-channel.h b/server/stream-channel.h
> index ba098df4..bd075a95 100644
> --- a/server/stream-channel.h
> +++ b/server/stream-channel.h
> @@ -48,7 +48,12 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
>   */
>  StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
>  
> -struct StreamMsgFormat;
> +/**
> + * Reset channel at initial state
> + */
> +void stream_channel_reset(StreamChannel *channel);
> +
> +struct StreamMsgStreamFormat;
>  struct StreamMsgStartStop;
>  
>  void stream_channel_change_format(StreamChannel *channel,
> diff --git a/server/stream-device.c b/server/stream-device.c
> index 8ab762a3..8909c9ba 100644
> --- a/server/stream-device.c
> +++ b/server/stream-device.c
> @@ -43,6 +43,7 @@ struct StreamDevice {
>      StreamDevHeader hdr;
>      uint8_t hdr_pos;
>      bool has_error;
> +    bool opened;
>      StreamChannel *stream_channel;
>  };
>  
> @@ -188,6 +189,35 @@ stream_device_remove_client(RedCharDevice *self,
> RedClient *client)
>  {
>  }
>  
> +static void
> +stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
> +                           StreamChannel *stream_channel
> G_GNUC_UNUSED)
> +{
> +    StreamDevice *dev = (StreamDevice *) opaque;
> +
> +    if (!dev->opened) {
> +        return;
> +    }
> +
> +    int msg_size = sizeof(*start) + sizeof(start->codecs[0]) *
> start->num_codecs;
> +    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 *hdr = (StreamDevHeader *)buf->buf;
> +    hdr->protocol_version = STREAM_DEVICE_PROTOCOL;
> +    hdr->padding = 0;
> +    hdr->type = GUINT16_TO_LE(STREAM_TYPE_START_STOP);
> +    hdr->size = GUINT32_TO_LE(msg_size);
> +
> +    memcpy(&hdr[1], start, msg_size);
> +
> +    red_char_device_write_buffer_add(char_dev, buf);
> +}
> +
>  RedCharDevice *
>  stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
>  {
> @@ -197,6 +227,7 @@ stream_device_connect(RedsState *reds,
> SpiceCharDeviceInstance *sin)
>  
>      StreamDevice *dev = stream_device_new(sin, reds);
>      dev->stream_channel = stream_channel;
> +    stream_channel_register_start_cb(stream_channel,
> stream_device_stream_start, dev);
>  
>      sif = spice_char_device_get_interface(sin);
>      if (sif->state) {
> @@ -219,6 +250,23 @@ stream_device_dispose(GObject *object)
>  }
>  
>  static void
> +stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
> +{
> +    if (event != SPICE_PORT_EVENT_OPENED && event !=
> SPICE_PORT_EVENT_CLOSED) {
> +        return;
> +    }
> +
> +    StreamDevice *device = STREAM_DEVICE(char_dev);
> +
> +    // reset device and channel on close/open
> +    device->opened = (event == SPICE_PORT_EVENT_OPENED);
> +    device->hdr_pos = 0;
> +    device->has_error = false;
> +    red_char_device_reset(char_dev);
> +    stream_channel_reset(device->stream_channel);
> +}
> +
> +static void
>  stream_device_class_init(StreamDeviceClass *klass)
>  {
>      GObjectClass *object_class = G_OBJECT_CLASS(klass);
> @@ -230,6 +278,7 @@ stream_device_class_init(StreamDeviceClass
> *klass)
>      char_dev_class->send_msg_to_client =
> stream_device_send_msg_to_client;
>      char_dev_class->send_tokens_to_client =
> stream_device_send_tokens_to_client;
>      char_dev_class->remove_client = stream_device_remove_client;
> +    char_dev_class->port_event = stream_device_port_event;
>  }
>  
>  static void


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



More information about the Spice-devel mailing list