summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2012-08-02 13:20:20 +0300
committerYonit Halperin <yhalperi@redhat.com>2012-08-27 09:13:00 +0300
commiteb4c95b08b6848ee604497bb66392636341ad1fe (patch)
tree87a1eaa15aa020ca057a71f808dc077993c86384
parent4f551a3550cf0d54e682e50ccddb446d15732bbe (diff)
downloadspice-eb4c95b08b6848ee604497bb66392636341ad1fe.tar.gz
spice-eb4c95b08b6848ee604497bb66392636341ad1fe.tar.xz
spice-eb4c95b08b6848ee604497bb66392636341ad1fe.zip
red_channel: handle sending SPICE_MSG_MIGRATE
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
-rw-r--r--server/inputs_channel.c3
-rw-r--r--server/main_channel.c5
-rw-r--r--server/red_channel.c38
-rw-r--r--server/red_channel.h14
-rw-r--r--server/red_worker.c23
-rw-r--r--server/smartcard.c4
-rw-r--r--server/spicevmc.c3
7 files changed, 69 insertions, 21 deletions
diff --git a/server/inputs_channel.c b/server/inputs_channel.c
index e14e995a..269e2dc4 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 61230682..63989657 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 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);
diff --git a/server/red_channel.h b/server/red_channel.h
index acb49cd0..35d11a61 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 bd6de1c8..69cd9aff 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,
@@ -8909,7 +8910,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;
@@ -8974,7 +8975,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;
@@ -9122,7 +9123,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,
@@ -9767,7 +9768,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;
@@ -10016,6 +10017,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,
@@ -10046,7 +10048,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;
@@ -10167,7 +10170,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:
@@ -10204,6 +10207,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,
@@ -10324,7 +10328,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);
}
}
@@ -10363,7 +10367,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);
@@ -10410,6 +10414,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 7ec44cb0..2ed0bde8 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 b96bf9f8..36d901f5 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;