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
This commit is contained in:
Yonit Halperin 2012-08-02 13:20:20 +03:00
parent 4f551a3550
commit eb4c95b08b
7 changed files with 69 additions and 21 deletions

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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,

View File

@ -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");

View File

@ -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;