The relevant code is common to all channels. The patch also contains a fix to the return value for handle_migrate_data callback: s/uint64_t/int --- server/inputs_channel.c | 3 ++- server/main_channel.c | 5 +++-- server/red_channel.c | 38 ++++++++++++++++++++++++++++++++++---- server/red_channel.h | 14 +++++++++++--- server/red_worker.c | 23 ++++++++++++++--------- server/smartcard.c | 4 +++- server/spicevmc.c | 3 ++- 7 files changed, 69 insertions(+), 21 deletions(-) diff --git a/server/inputs_channel.c b/server/inputs_channel.c index e14e995..269e2dc 100644 --- a/server/inputs_channel.c +++ b/server/inputs_channel.c @@ -551,7 +551,8 @@ void inputs_init(void) FALSE, /* handle_acks */ spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL), inputs_channel_handle_parsed, - &channel_cbs); + &channel_cbs, + 0); if (!g_inputs_channel) { spice_error("failed to allocate Inputs Channel"); diff --git a/server/main_channel.c b/server/main_channel.c index 6123068..6398965 100644 --- a/server/main_channel.c +++ b/server/main_channel.c @@ -475,7 +475,7 @@ static uint64_t main_channel_handle_migrate_data_get_serial(RedChannelClient *ba return data->serial; } -static uint64_t main_channel_handle_migrate_data(RedChannelClient *base, +static int main_channel_handle_migrate_data(RedChannelClient *base, uint32_t size, void *message) { MainChannelClient *mcc = SPICE_CONTAINEROF(base, MainChannelClient, base); @@ -1138,7 +1138,8 @@ MainChannel* main_channel_init(void) FALSE, FALSE, /* handle_acks */ spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL), main_channel_handle_parsed, - &channel_cbs); + &channel_cbs, + SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER); spice_assert(channel); red_channel_set_cap(channel, SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE); diff --git a/server/red_channel.c b/server/red_channel.c index a108bc2..d715ce8 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -452,6 +452,20 @@ static void red_channel_client_send_set_ack(RedChannelClient *rcc) red_channel_client_begin_send_message(rcc); } +static void red_channel_client_send_migrate(RedChannelClient *rcc) +{ + SpiceMsgMigrate migrate; + + red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, NULL); + migrate.flags = rcc->channel->migration_flags; + spice_marshall_msg_migrate(rcc->send_data.marshaller, &migrate); + if (rcc->channel->migration_flags & SPICE_MIGRATE_NEED_FLUSH) { + rcc->wait_migrate_flush_mark = TRUE; + } + + red_channel_client_begin_send_message(rcc); +} + static void red_channel_client_send_item(RedChannelClient *rcc, PipeItem *item) { int handled = TRUE; @@ -463,6 +477,10 @@ static void red_channel_client_send_item(RedChannelClient *rcc, PipeItem *item) red_channel_client_send_set_ack(rcc); free(item); break; + case PIPE_ITEM_TYPE_MIGRATE: + red_channel_client_send_migrate(rcc); + free(item); + break; default: handled = FALSE; } @@ -684,8 +702,9 @@ static void red_channel_client_default_disconnect(RedChannelClient *base) red_channel_client_disconnect(base); } -static void red_channel_client_default_migrate(RedChannelClient *base) +void red_channel_client_default_migrate(RedChannelClient *rcc) { + red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_MIGRATE); } RedChannel *red_channel_create(int size, @@ -693,7 +712,8 @@ RedChannel *red_channel_create(int size, uint32_t type, uint32_t id, int migrate, int handle_acks, channel_handle_message_proc handle_message, - ChannelCbs *channel_cbs) + ChannelCbs *channel_cbs, + uint32_t migration_flags) { RedChannel *channel; ClientCbs client_cbs = { NULL, }; @@ -701,11 +721,14 @@ RedChannel *red_channel_create(int size, spice_assert(size >= sizeof(*channel)); spice_assert(channel_cbs->config_socket && channel_cbs->on_disconnect && handle_message && channel_cbs->alloc_recv_buf && channel_cbs->release_item); + spice_assert(channel_cbs->handle_migrate_data || + !(migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER)); channel = spice_malloc0(size); channel->type = type; channel->id = id; channel->refs = 1; channel->handle_acks = handle_acks; + channel->migration_flags = migration_flags; memcpy(&channel->channel_cbs, channel_cbs, sizeof(ChannelCbs)); channel->core = core; @@ -801,12 +824,14 @@ RedChannel *red_channel_create_parser(int size, int migrate, int handle_acks, spice_parse_channel_func_t parser, channel_handle_parsed_proc handle_parsed, - ChannelCbs *channel_cbs) + ChannelCbs *channel_cbs, + uint32_t migration_flags) { RedChannel *channel = red_channel_create(size, core, type, id, migrate, handle_acks, do_nothing_handle_message, - channel_cbs); + channel_cbs, + migration_flags); if (channel == NULL) { return NULL; @@ -1089,7 +1114,12 @@ int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size, case SPICE_MSGC_DISCONNECTING: break; case SPICE_MSGC_MIGRATE_FLUSH_MARK: + if (!rcc->wait_migrate_flush_mark) { + spice_error("unexpected flush mark"); + return FALSE; + } red_channel_handle_migrate_flush_mark(rcc); + rcc->wait_migrate_flush_mark = FALSE; break; case SPICE_MSGC_MIGRATE_DATA: red_channel_handle_migrate_data(rcc, size, message); diff --git a/server/red_channel.h b/server/red_channel.h index acb49cd..35d11a6 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -142,6 +142,8 @@ typedef struct MainChannelClient MainChannelClient; * */ enum { PIPE_ITEM_TYPE_SET_ACK=1, + PIPE_ITEM_TYPE_MIGRATE, + PIPE_ITEM_TYPE_CHANNEL_BASE=101, }; @@ -168,7 +170,7 @@ typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc); typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc); typedef int (*channel_handle_migrate_flush_mark_proc)(RedChannelClient *base); -typedef uint64_t (*channel_handle_migrate_data_proc)(RedChannelClient *base, +typedef int (*channel_handle_migrate_data_proc)(RedChannelClient *base, uint32_t size, void *message); typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient *base, uint32_t size, void *message); @@ -265,6 +267,7 @@ struct RedChannelClient { RedChannelCapabilities remote_caps; int is_mini_header; int destroying; + int wait_migrate_flush_mark; }; struct RedChannel { @@ -296,6 +299,7 @@ struct RedChannel { ClientCbs client_cbs; RedChannelCapabilities local_caps; + uint32_t migration_flags; void *data; @@ -313,7 +317,8 @@ RedChannel *red_channel_create(int size, uint32_t type, uint32_t id, int migrate, int handle_acks, channel_handle_message_proc handle_message, - ChannelCbs *channel_cbs); + ChannelCbs *channel_cbs, + uint32_t migration_flags); /* alternative constructor, meant for marshaller based (inputs,main) channels, * will become default eventually */ @@ -323,7 +328,8 @@ RedChannel *red_channel_create_parser(int size, int migrate, int handle_acks, spice_parse_channel_func_t parser, channel_handle_parsed_proc handle_parsed, - ChannelCbs *channel_cbs); + ChannelCbs *channel_cbs, + uint32_t migration_flags); void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs); // caps are freed when the channel is destroyed @@ -350,6 +356,8 @@ void red_channel_client_destroy_dummy(RedChannelClient *rcc); int red_channel_is_connected(RedChannel *channel); int red_channel_client_is_connected(RedChannelClient *rcc); +void red_channel_client_default_migrate(RedChannelClient *rcc); + /* * the disconnect callback is called from the channel's thread, * i.e., for display channels - red worker thread, for all the other - from the main thread. diff --git a/server/red_worker.c b/server/red_worker.c index 9330fff..7c71ba0 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -253,7 +253,8 @@ enum { PIPE_ITEM_TYPE_DRAW = PIPE_ITEM_TYPE_CHANNEL_BASE, PIPE_ITEM_TYPE_INVAL_ONE, PIPE_ITEM_TYPE_CURSOR, - PIPE_ITEM_TYPE_MIGRATE, + PIPE_ITEM_TYPE_DISPLAY_MIGRATE, /* tmp. It will be substituted with + red_channel/PIPE_ITEM_TYPE_MIGRATE */ PIPE_ITEM_TYPE_CURSOR_INIT, PIPE_ITEM_TYPE_IMAGE, PIPE_ITEM_TYPE_STREAM_CREATE, @@ -8798,7 +8799,7 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item case PIPE_ITEM_TYPE_VERB: red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb); break; - case PIPE_ITEM_TYPE_MIGRATE: + case PIPE_ITEM_TYPE_DISPLAY_MIGRATE: spice_info("PIPE_ITEM_TYPE_MIGRATE"); display_channel_marshall_migrate(rcc, m); break; @@ -8863,7 +8864,7 @@ static void cursor_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item) case PIPE_ITEM_TYPE_VERB: red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb); break; - case PIPE_ITEM_TYPE_MIGRATE: + case PIPE_ITEM_TYPE_DISPLAY_MIGRATE: spice_info("PIPE_ITEM_TYPE_MIGRATE"); cursor_channel_marshall_migrate(rcc, m); break; @@ -9011,7 +9012,7 @@ static void red_migrate_display(RedWorker *worker, RedChannelClient *rcc) // TODO: replace all worker->display_channel tests with // is_connected if (red_channel_client_is_connected(rcc)) { - red_pipe_add_verb(rcc, PIPE_ITEM_TYPE_MIGRATE); + red_pipe_add_verb(rcc, PIPE_ITEM_TYPE_DISPLAY_MIGRATE); // red_pipes_add_verb(&worker->display_channel->common.base, // SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL); // red_channel_pipes_add_type(&worker->display_channel->common.base, @@ -9656,7 +9657,7 @@ static uint64_t display_channel_handle_migrate_data_get_serial( return migrate_data->message_serial; } -static uint64_t display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size, +static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message) { DisplayChannelMigrateData *migrate_data; @@ -9905,6 +9906,7 @@ CursorChannelClient *cursor_channel_create_rcc(CommonChannel *common, } static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_type, int migrate, + int migration_flags, channel_disconnect_proc on_disconnect, channel_send_pipe_item_proc send_item, channel_hold_pipe_item_proc hold_item, @@ -9935,7 +9937,8 @@ static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_t TRUE /* handle_acks */, spice_get_client_channel_parser(channel_type, NULL), handle_parsed, - &channel_cbs); + &channel_cbs, + migration_flags); common = (CommonChannel *)channel; if (!channel) { goto error; @@ -10056,7 +10059,7 @@ static void display_channel_client_release_item_before_push(DisplayChannelClient } case PIPE_ITEM_TYPE_INVAL_ONE: case PIPE_ITEM_TYPE_VERB: - case PIPE_ITEM_TYPE_MIGRATE: + case PIPE_ITEM_TYPE_DISPLAY_MIGRATE: case PIPE_ITEM_TYPE_MIGRATE_DATA: case PIPE_ITEM_TYPE_PIXMAP_SYNC: case PIPE_ITEM_TYPE_PIXMAP_RESET: @@ -10093,6 +10096,7 @@ static void display_channel_create(RedWorker *worker, int migrate) if (!(worker->display_channel = (DisplayChannel *)__new_channel( worker, sizeof(*display_channel), SPICE_CHANNEL_DISPLAY, migrate, + SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, display_channel_client_on_disconnect, display_channel_send_item, display_channel_hold_pipe_item, @@ -10213,7 +10217,7 @@ static void red_migrate_cursor(RedWorker *worker, RedChannelClient *rcc) red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE); red_channel_client_pipe_add_type(rcc, - PIPE_ITEM_TYPE_MIGRATE); + PIPE_ITEM_TYPE_DISPLAY_MIGRATE); } } @@ -10252,7 +10256,7 @@ static void cursor_channel_client_release_item_before_push(CursorChannelClient * } case PIPE_ITEM_TYPE_INVAL_ONE: case PIPE_ITEM_TYPE_VERB: - case PIPE_ITEM_TYPE_MIGRATE: + case PIPE_ITEM_TYPE_DISPLAY_MIGRATE: case PIPE_ITEM_TYPE_CURSOR_INIT: case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: free(item); @@ -10299,6 +10303,7 @@ static void cursor_channel_create(RedWorker *worker, int migrate) worker->cursor_channel = (CursorChannel *)__new_channel( worker, sizeof(*worker->cursor_channel), SPICE_CHANNEL_CURSOR, migrate, + 0, cursor_channel_client_on_disconnect, cursor_channel_send_item, cursor_channel_hold_pipe_item, diff --git a/server/smartcard.c b/server/smartcard.c index 7ec44cb..2ed0bde 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -679,6 +679,7 @@ static void smartcard_init(void) { ChannelCbs channel_cbs = { NULL, }; ClientCbs client_cbs = { NULL, }; + uint32_t migration_flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER; spice_assert(!g_smartcard_channel); @@ -695,7 +696,8 @@ static void smartcard_init(void) FALSE /* migration - TODO?*/, FALSE /* handle_acks */, smartcard_channel_handle_message, - &channel_cbs); + &channel_cbs, + migration_flags); if (!g_smartcard_channel) { spice_error("failed to allocate Smartcard Channel"); diff --git a/server/spicevmc.c b/server/spicevmc.c index b96bf9f..36d901f 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -343,7 +343,8 @@ SpiceCharDeviceState *spicevmc_device_connect(SpiceCharDeviceInstance *sin, FALSE /* migration - TODO? */, FALSE /* handle_acks */, spicevmc_red_channel_client_handle_message, - &channel_cbs); + &channel_cbs, + SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER); red_channel_init_outgoing_messages_window(&state->channel); client_cbs.connect = spicevmc_connect; -- 1.7.7.6 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel