This new private method is to reset the channel to its initial state, used by semi-seamless migration --- gtk/channel-cursor.c | 12 ++++++++++ gtk/channel-display.c | 18 ++++++++++++++ gtk/channel-main.c | 41 ++++++++++++++++++++++++++++++++- gtk/channel-playback.c | 19 +++++++++++++++ gtk/channel-record.c | 21 +++++++++++++++++ gtk/channel-smartcard.c | 56 +++++++++++++++++++++++++++++++++------------ gtk/channel-usbredir.c | 8 ++++++ gtk/spice-channel-priv.h | 2 + gtk/spice-channel.c | 35 +++++++++++++++++++++------- gtk/spice-channel.h | 4 ++- 10 files changed, 190 insertions(+), 26 deletions(-)
diff --git a/gtk/channel-cursor.c b/gtk/channel-cursor.c index 4ad402c..6766b40 100644 --- a/gtk/channel-cursor.c +++ b/gtk/channel-cursor.c @@ -92,6 +92,17 @@ static void spice_cursor_channel_finalize(GObject *obj) G_OBJECT_CLASS(spice_cursor_channel_parent_class)->finalize(obj); } +/* coroutine context */ +static void spice_cursor_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceCursorChannelPrivate *c = SPICE_CURSOR_CHANNEL(channel)->priv; + + delete_cursor_all(channel); + c->init_done = FALSE; + + SPICE_CHANNEL_CLASS(spice_cursor_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -99,6 +110,7 @@ static void spice_cursor_channel_class_init(SpiceCursorChannelClass *klass) gobject_class->finalize = spice_cursor_channel_finalize; channel_class->handle_msg = spice_cursor_handle_msg; + channel_class->channel_reset = spice_cursor_channel_reset; /** * SpiceCursorChannel::cursor-set: diff --git a/gtk/channel-display.c b/gtk/channel-display.c index 120128f..47beaa1 100644 --- a/gtk/channel-display.c +++ b/gtk/channel-display.c @@ -73,6 +73,7 @@ struct _SpiceDisplayChannelPrivate { #ifdef WIN32 HDC dc; #endif + gboolean migrate_wait_primary; }; G_DEFINE_TYPE(SpiceDisplayChannel, spice_display_channel, SPICE_TYPE_CHANNEL) @@ -103,6 +104,8 @@ static void clear_surfaces(SpiceChannel *channel); static void clear_streams(SpiceChannel *channel); static display_surface *find_surface(SpiceDisplayChannelPrivate *c, int surface_id); static gboolean display_stream_render(display_stream *st); +static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating); +static void destroy_canvas(display_surface *surface); /* ------------------------------------------------------------------ */ @@ -181,6 +184,20 @@ static void spice_display_set_property(GObject *object, } } +/* main or coroutine context */ +static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv; + + /* palettes, images, and glz_window are cleared in the session */ + + c->migrate_wait_primary = migrating; + clear_streams(channel); + clear_surfaces(channel); + + SPICE_CHANNEL_CLASS(spice_display_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -194,6 +211,7 @@ static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass) channel_class->handle_msg = spice_display_handle_msg; channel_class->channel_up = spice_display_channel_up; + channel_class->channel_reset = spice_display_channel_reset; g_object_class_install_property (gobject_class, PROP_HEIGHT, diff --git a/gtk/channel-main.c b/gtk/channel-main.c index 615cdf6..47e41ab 100644 --- a/gtk/channel-main.c +++ b/gtk/channel-main.c @@ -122,6 +122,7 @@ static guint signals[SPICE_MAIN_LAST_SIGNAL]; static void spice_main_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg); static void agent_send_msg_queue(SpiceMainChannel *channel); +static void agent_free_msg_queue(SpiceMainChannel *channel); static void migrate_channel_event_cb(SpiceChannel *channel, SpiceChannelEvent event, gpointer data); @@ -250,7 +251,7 @@ static void spice_main_channel_finalize(GObject *obj) SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(obj)->priv; g_free(c->agent_msg_data); - g_queue_free(c->agent_msg_queue); + agent_free_msg_queue(SPICE_MAIN_CHANNEL(obj)); if (G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize) G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize(obj); @@ -265,6 +266,26 @@ static void spice_channel_iterate_write(SpiceChannel *channel) SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->iterate_write(channel); } +/* main or coroutine context */ +static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv; + + c->agent_connected = FALSE; + c->agent_caps_received = FALSE; + c->agent_display_config_sent = FALSE; + c->agent_tokens = 0; + c->agent_msg_pos = 0; + g_free(c->agent_msg_data); + c->agent_msg_data = NULL; + c->agent_msg_size = 0; + + agent_free_msg_queue(SPICE_MAIN_CHANNEL(channel)); + c->agent_msg_queue = g_queue_new(); + + SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_main_channel_class_init(SpiceMainChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -277,6 +298,7 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass) channel_class->handle_msg = spice_main_handle_msg; channel_class->iterate_write = spice_channel_iterate_write; + channel_class->channel_reset = spice_main_channel_reset; /** * SpiceMainChannel:mouse-mode: @@ -706,6 +728,23 @@ static void do_emit_main_context(GObject *object, int signum, gpointer params) /* ------------------------------------------------------------------ */ +static void agent_free_msg_queue(SpiceMainChannel *channel) +{ + SpiceMainChannelPrivate *c = channel->priv; + SpiceMsgOut *out; + + if (!c->agent_msg_queue) + return; + + while (!g_queue_is_empty(c->agent_msg_queue)) { + out = g_queue_pop_head(c->agent_msg_queue); + spice_msg_out_unref(out); + } + + g_queue_free(c->agent_msg_queue); + c->agent_msg_queue = NULL; +} + /* coroutine context */ static void agent_send_msg_queue(SpiceMainChannel *channel) { diff --git a/gtk/channel-playback.c b/gtk/channel-playback.c index 4804682..32f8b1a 100644 --- a/gtk/channel-playback.c +++ b/gtk/channel-playback.c @@ -154,6 +154,24 @@ static void spice_playback_channel_set_property(GObject *gobject, } } +/* main or coroutine context */ +static void spice_playback_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpicePlaybackChannelPrivate *c = SPICE_PLAYBACK_CHANNEL(channel)->priv; + + if (c->celt_decoder) { + celt051_decoder_destroy(c->celt_decoder); + c->celt_decoder = NULL; + } + + if (c->celt_mode) { + celt051_mode_destroy(c->celt_mode); + c->celt_mode = NULL; + } + + SPICE_CHANNEL_CLASS(spice_playback_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -164,6 +182,7 @@ static void spice_playback_channel_class_init(SpicePlaybackChannelClass *klass) gobject_class->set_property = spice_playback_channel_set_property; channel_class->handle_msg = spice_playback_handle_msg; + channel_class->channel_reset = spice_playback_channel_reset; g_object_class_install_property (gobject_class, PROP_NCHANNELS, diff --git a/gtk/channel-record.c b/gtk/channel-record.c index 4e5e893..c5aded9 100644 --- a/gtk/channel-record.c +++ b/gtk/channel-record.c @@ -163,6 +163,26 @@ static void spice_record_channel_set_property(GObject *gobject, } } +static void channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceRecordChannelPrivate *c = SPICE_RECORD_CHANNEL(channel)->priv; + + g_free(c->last_frame); + c->last_frame = NULL; + + if (c->celt_encoder) { + celt051_encoder_destroy(c->celt_encoder); + c->celt_encoder = NULL; + } + + if (c->celt_mode) { + celt051_mode_destroy(c->celt_mode); + c->celt_mode = NULL; + } + + SPICE_CHANNEL_CLASS(spice_record_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_record_channel_class_init(SpiceRecordChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -173,6 +193,7 @@ static void spice_record_channel_class_init(SpiceRecordChannelClass *klass) gobject_class->set_property = spice_record_channel_set_property; channel_class->handle_msg = spice_record_handle_msg; channel_class->channel_up = channel_up; + channel_class->channel_reset = channel_reset; g_object_class_install_property (gobject_class, PROP_NCHANNELS, diff --git a/gtk/channel-smartcard.c b/gtk/channel-smartcard.c index 98e77eb..6fa4435 100644 --- a/gtk/channel-smartcard.c +++ b/gtk/channel-smartcard.c @@ -144,31 +144,56 @@ static void spice_smartcard_channel_init(SpiceSmartcardChannel *channel) static void spice_smartcard_channel_finalize(GObject *obj) { - SpiceSmartcardChannel *channel = SPICE_SMARTCARD_CHANNEL(obj); + SpiceSmartcardChannelPrivate *c = SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(obj); - if (channel->priv->pending_card_insertions != NULL) { - g_hash_table_destroy(channel->priv->pending_card_insertions); - channel->priv->pending_card_insertions = NULL; + if (c->pending_card_insertions != NULL) { + g_hash_table_destroy(c->pending_card_insertions); + c->pending_card_insertions = NULL; } - if (channel->priv->pending_reader_removals != NULL) { - g_hash_table_destroy(channel->priv->pending_reader_removals); - channel->priv->pending_reader_removals = NULL; + if (c->pending_reader_removals != NULL) { + g_hash_table_destroy(c->pending_reader_removals); + c->pending_reader_removals = NULL; } - if (channel->priv->message_queue != NULL) { - g_queue_foreach(channel->priv->message_queue, - (GFunc)smartcard_message_free, NULL); - g_queue_free(channel->priv->message_queue); - channel->priv->message_queue = NULL; + if (c->message_queue != NULL) { + g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL); + g_queue_free(c->message_queue); + c->message_queue = NULL; } - if (channel->priv->in_flight_message != NULL) { - smartcard_message_free(channel->priv->in_flight_message); - channel->priv->in_flight_message = NULL; + if (c->in_flight_message != NULL) { + smartcard_message_free(c->in_flight_message); + c->in_flight_message = NULL; } + g_list_free(c->pending_reader_additions); + c->pending_reader_additions = NULL; + if (G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize) G_OBJECT_CLASS(spice_smartcard_channel_parent_class)->finalize(obj); } +static void spice_smartcard_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SpiceSmartcardChannelPrivate *c = SPICE_SMARTCARD_CHANNEL_GET_PRIVATE(channel); + + g_hash_table_remove_all(c->pending_card_insertions); + g_hash_table_remove_all(c->pending_reader_removals); + + if (c->message_queue != NULL) { + g_queue_foreach(c->message_queue, (GFunc)smartcard_message_free, NULL); + g_queue_clear(c->message_queue); + } + + if (c->in_flight_message != NULL) { + smartcard_message_free(c->in_flight_message); + c->in_flight_message = NULL; + } + + g_list_free(c->pending_reader_additions); + c->pending_reader_additions = NULL; + + SPICE_CHANNEL_CLASS(spice_smartcard_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); @@ -177,6 +202,7 @@ static void spice_smartcard_channel_class_init(SpiceSmartcardChannelClass *klass gobject_class->finalize = spice_smartcard_channel_finalize; channel_class->handle_msg = spice_smartcard_handle_msg; channel_class->channel_up = spice_smartcard_channel_up; + channel_class->channel_reset = spice_smartcard_channel_reset; g_type_class_add_private(klass, sizeof(SpiceSmartcardChannelPrivate)); } diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c index 06d80d5..cdc04a9 100644 --- a/gtk/channel-usbredir.c +++ b/gtk/channel-usbredir.c @@ -102,6 +102,13 @@ static void spice_usbredir_channel_init(SpiceUsbredirChannel *channel) #endif } +static void spice_usbredir_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + spice_usbredir_channel_disconnect(SPICE_USBREDIR_CHANNEL(channel)); + + SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(channel, migrating); +} + static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass) { #ifdef USE_USBREDIR @@ -111,6 +118,7 @@ static void spice_usbredir_channel_class_init(SpiceUsbredirChannelClass *klass) gobject_class->dispose = spice_usbredir_channel_dispose; channel_class->handle_msg = spice_usbredir_handle_msg; channel_class->channel_up = spice_usbredir_channel_up; + channel_class->channel_reset = spice_usbredir_channel_reset; g_type_class_add_private(klass, sizeof(SpiceUsbredirChannelPrivate)); #endif diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h index ed5f3a7..5585f13 100644 --- a/gtk/spice-channel-priv.h +++ b/gtk/spice-channel-priv.h @@ -166,6 +166,8 @@ void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap); void spice_channel_set_common_capability(SpiceChannel *channel, guint32 cap); gboolean spice_channel_get_read_only(SpiceChannel *channel); +void spice_channel_reset(SpiceChannel *channel, gboolean migrating); + /* coroutine context */ #define emit_main_context(object, event, args...) \ G_STMT_START { \ diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c index b6779ba..6420c53 100644 --- a/gtk/spice-channel.c +++ b/gtk/spice-channel.c @@ -45,6 +45,7 @@ static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg); static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out); static void spice_channel_send_link(SpiceChannel *channel); static void channel_disconnect(SpiceChannel *channel); +static void channel_reset(SpiceChannel *channel, gboolean migrating); /** * SECTION:spice-channel @@ -249,6 +250,7 @@ static void spice_channel_class_init(SpiceChannelClass *klass) klass->iterate_write = spice_channel_iterate_write; klass->iterate_read = spice_channel_iterate_read; klass->channel_disconnect = channel_disconnect; + klass->channel_reset = channel_reset; gobject_class->constructed = spice_channel_constructed; gobject_class->dispose = spice_channel_dispose; @@ -2116,18 +2118,10 @@ gboolean spice_channel_open_fd(SpiceChannel *channel, int fd) } /* system or coroutine context */ -static void channel_disconnect(SpiceChannel *channel) +static void channel_reset(SpiceChannel *channel, gboolean migrating) { SpiceChannelPrivate *c = SPICE_CHANNEL_GET_PRIVATE(channel); - g_return_if_fail(c != NULL); - - if (c->state == SPICE_CHANNEL_STATE_UNCONNECTED) { - return; - } - - c->has_error = TRUE; /* break the loop */ - if (c->connect_delayed_id) { g_source_remove(c->connect_delayed_id); c->connect_delayed_id = 0; @@ -2174,9 +2168,32 @@ static void channel_disconnect(SpiceChannel *channel) g_array_set_size(c->caps, 0); /* Restore our default capabilities in case the channel gets re-used */ spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION); +} + +/* system or coroutine context */ +G_GNUC_INTERNAL +void spice_channel_reset(SpiceChannel *channel, gboolean migrating) +{ + SPICE_CHANNEL_GET_CLASS(channel)->channel_reset(channel, migrating); +} + +/* system or coroutine context */ +static void channel_disconnect(SpiceChannel *channel) +{ + SpiceChannelPrivate *c = SPICE_CHANNEL_GET_PRIVATE(channel); + + g_return_if_fail(c != NULL); + + if (c->state == SPICE_CHANNEL_STATE_UNCONNECTED) + return; + + c->has_error = TRUE; /* break the loop */ + + spice_channel_reset(channel, FALSE); if (c->state == SPICE_CHANNEL_STATE_READY) emit_main_context(channel, SPICE_CHANNEL_EVENT, SPICE_CHANNEL_CLOSED); + g_return_if_fail(SPICE_IS_CHANNEL(channel)); c->state = SPICE_CHANNEL_STATE_UNCONNECTED; } diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h index 793c5d6..2a8e7e7 100644 --- a/gtk/spice-channel.h +++ b/gtk/spice-channel.h @@ -87,11 +87,13 @@ struct _SpiceChannelClass /*< private >*/ /* virtual method, any context */ void (*channel_disconnect)(SpiceChannel *channel); + + void (*channel_reset)(SpiceChannel *channel, gboolean migrating); /* * If adding fields to this struct, remove corresponding * amount of padding to avoid changing overall struct size */ - gchar _spice_reserved[SPICE_RESERVED_PADDING - 4 * sizeof(void*)]; + gchar _spice_reserved[SPICE_RESERVED_PADDING - 5 * sizeof(void*)]; }; GType spice_channel_get_type(void); -- 1.7.7.4 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel