summaryrefslogtreecommitdiffstats
path: root/server/red_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/red_channel.c')
-rw-r--r--server/red_channel.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/server/red_channel.c b/server/red_channel.c
index a108bc21..d715ce8c 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);