mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 14:41:25 +00:00
server,proto: tell the clients to connect to the migration target before migraton starts
(1) send SPICE_MSG_MAIN_MIGRATE_BEGIN upon spice_server_migrate_connect
(to all the clients that support it)
(2) wait for SPICE_MSGC_MAIN_MIGRATE_(CONNECTED|CONNECT_ERROR) from all the relevant clients,
or a timeout, in order to complete client_migrate_info monitor command
(cherry picked from commit 5560c56ef0 branch 0.8;
Was modified to support the separation of main channel from reds, and multiple clients)
Conflicts:
server/reds.c
This commit is contained in:
parent
fc3aa53211
commit
70d1161430
@ -66,6 +66,8 @@ typedef struct SpiceMsgMainMigrationBegin {
|
||||
uint16_t pub_key_type;
|
||||
uint32_t pub_key_size;
|
||||
uint8_t *pub_key_data;
|
||||
uint32_t cert_subject_size;
|
||||
uint8_t *cert_subject_data;
|
||||
} SpiceMsgMainMigrationBegin;
|
||||
|
||||
typedef struct SpiceMsgMainMigrationSwitchHost {
|
||||
|
||||
@ -110,16 +110,6 @@ typedef struct NotifyPipeItem {
|
||||
int mess_len;
|
||||
} NotifyPipeItem;
|
||||
|
||||
typedef struct MigrateBeginPipeItem {
|
||||
PipeItem base;
|
||||
int port;
|
||||
int sport;
|
||||
char *host;
|
||||
uint16_t cert_pub_key_type;
|
||||
uint32_t cert_pub_key_len;
|
||||
uint8_t *cert_pub_key;
|
||||
} MigrateBeginPipeItem;
|
||||
|
||||
typedef struct MultiMediaTimePipeItem {
|
||||
PipeItem base;
|
||||
int time;
|
||||
@ -137,6 +127,8 @@ struct MainChannelClient {
|
||||
SpiceTimer *ping_timer;
|
||||
int ping_interval;
|
||||
#endif
|
||||
int mig_wait_connect;
|
||||
int mig_connect_ok;
|
||||
};
|
||||
|
||||
enum NetTestStage {
|
||||
@ -283,33 +275,6 @@ static PipeItem *main_notify_item_new(RedChannelClient *rcc, void *data, int num
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
typedef struct MigrateBeginItemInfo {
|
||||
int port;
|
||||
int sport;
|
||||
char *host;
|
||||
uint16_t cert_pub_key_type;
|
||||
uint32_t cert_pub_key_len;
|
||||
uint8_t *cert_pub_key;
|
||||
} MigrateBeginItemInfo;
|
||||
|
||||
// TODO: MC: migration is not tested at all with multiclient.
|
||||
static PipeItem *main_migrate_begin_item_new(
|
||||
RedChannelClient *rcc, void *data, int num)
|
||||
{
|
||||
MigrateBeginPipeItem *item = spice_malloc(sizeof(MigrateBeginPipeItem));
|
||||
MigrateBeginItemInfo *info = data;
|
||||
|
||||
red_channel_pipe_item_init(rcc->channel, &item->base,
|
||||
SPICE_MSG_MAIN_MIGRATE_BEGIN);
|
||||
item->port = info->port;
|
||||
item->sport = info->sport;
|
||||
item->host = info->host;
|
||||
item->cert_pub_key_type = info->cert_pub_key_type;
|
||||
item->cert_pub_key_len = info->cert_pub_key_len;
|
||||
item->cert_pub_key = info->cert_pub_key;
|
||||
return &item->base;
|
||||
}
|
||||
|
||||
static PipeItem *main_multi_media_time_item_new(
|
||||
RedChannelClient *rcc, void *data, int num)
|
||||
{
|
||||
@ -550,35 +515,23 @@ static void main_channel_marshall_notify(SpiceMarshaller *m, NotifyPipeItem *ite
|
||||
spice_marshaller_add(m, item->mess, item->mess_len + 1);
|
||||
}
|
||||
|
||||
void main_channel_push_migrate_begin(MainChannel *main_chan, int port, int sport,
|
||||
char *host, uint16_t cert_pub_key_type, uint32_t cert_pub_key_len,
|
||||
uint8_t *cert_pub_key)
|
||||
{
|
||||
MigrateBeginItemInfo info = {
|
||||
.port =port,
|
||||
.sport = sport,
|
||||
.host = host,
|
||||
.cert_pub_key_type = cert_pub_key_type,
|
||||
.cert_pub_key_len = cert_pub_key_len,
|
||||
.cert_pub_key = cert_pub_key,
|
||||
};
|
||||
|
||||
red_channel_pipes_new_add_push(&main_chan->base,
|
||||
main_migrate_begin_item_new, &info);
|
||||
}
|
||||
|
||||
static void main_channel_marshall_migrate_begin(SpiceMarshaller *m,
|
||||
MigrateBeginPipeItem *item)
|
||||
static void main_channel_marshall_migrate_begin(SpiceMarshaller *m, RedChannelClient *rcc)
|
||||
{
|
||||
SpiceMsgMainMigrationBegin migrate;
|
||||
MainChannel *main_ch;
|
||||
|
||||
migrate.port = item->port;
|
||||
migrate.sport = item->sport;
|
||||
migrate.host_size = strlen(item->host) + 1;
|
||||
migrate.host_data = (uint8_t *)item->host;
|
||||
migrate.pub_key_type = item->cert_pub_key_type;
|
||||
migrate.pub_key_size = item->cert_pub_key_len;
|
||||
migrate.pub_key_data = item->cert_pub_key;
|
||||
main_ch = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
|
||||
migrate.port = main_ch->mig_target.port;
|
||||
migrate.sport = main_ch->mig_target.sport;
|
||||
migrate.host_size = strlen(main_ch->mig_target.host) + 1;
|
||||
migrate.host_data = (uint8_t *)main_ch->mig_target.host;
|
||||
if (main_ch->mig_target.cert_subject) {
|
||||
migrate.cert_subject_size = strlen(main_ch->mig_target.cert_subject) + 1;
|
||||
migrate.cert_subject_data = (uint8_t *)main_ch->mig_target.cert_subject;
|
||||
} else {
|
||||
migrate.cert_subject_size = 0;
|
||||
migrate.cert_subject_data = NULL;
|
||||
}
|
||||
spice_marshall_msg_main_migrate_begin(m, &migrate);
|
||||
}
|
||||
|
||||
@ -699,8 +652,7 @@ static void main_channel_send_item(RedChannelClient *rcc, PipeItem *base)
|
||||
main_channel_marshall_migrate(m);
|
||||
break;
|
||||
case SPICE_MSG_MAIN_MIGRATE_BEGIN:
|
||||
main_channel_marshall_migrate_begin(m,
|
||||
SPICE_CONTAINEROF(base, MigrateBeginPipeItem, base));
|
||||
main_channel_marshall_migrate_begin(m, rcc);
|
||||
break;
|
||||
case SPICE_MSG_MAIN_MULTI_MEDIA_TIME:
|
||||
main_channel_marshall_multi_media_time(m,
|
||||
@ -741,6 +693,26 @@ static void main_channel_release_pipe_item(RedChannelClient *rcc,
|
||||
free(base);
|
||||
}
|
||||
|
||||
void main_channel_client_handle_migrate_connected(MainChannelClient *mcc, int success)
|
||||
{
|
||||
red_printf("client %p connected: %d", mcc->base.client, success);
|
||||
if (mcc->mig_wait_connect) {
|
||||
MainChannel *main_channel = SPICE_CONTAINEROF(mcc->base.channel, MainChannel, base);
|
||||
|
||||
mcc->mig_wait_connect = FALSE;
|
||||
mcc->mig_connect_ok = success;
|
||||
ASSERT(main_channel->num_clients_mig_wait);
|
||||
if (!--main_channel->num_clients_mig_wait) {
|
||||
reds_on_main_migrate_connected();
|
||||
}
|
||||
} else {
|
||||
if (success) {
|
||||
red_printf("client %p MIGRATE_CANCEL", mcc->base.client);
|
||||
red_channel_client_pipe_add_type(&mcc->base, SPICE_MSG_MAIN_MIGRATE_CANCEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
|
||||
{
|
||||
MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
|
||||
@ -764,12 +736,10 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint
|
||||
main_channel_push_channels(mcc);
|
||||
break;
|
||||
case SPICE_MSGC_MAIN_MIGRATE_CONNECTED:
|
||||
red_printf("connected");
|
||||
reds_on_main_migrate_connected();
|
||||
main_channel_client_handle_migrate_connected(mcc, TRUE);
|
||||
break;
|
||||
case SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR:
|
||||
red_printf("mig connect error");
|
||||
reds_on_main_migrate_connect_error();
|
||||
main_channel_client_handle_migrate_connected(mcc, FALSE);
|
||||
break;
|
||||
case SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST:
|
||||
reds_on_main_mouse_mode_request(message, size);
|
||||
@ -1001,6 +971,58 @@ MainChannel* main_channel_init(void)
|
||||
main_channel_handle_parsed,
|
||||
&channel_cbs);
|
||||
ASSERT(channel);
|
||||
|
||||
red_channel_set_cap(channel, SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
|
||||
return (MainChannel *)channel;
|
||||
}
|
||||
|
||||
RedChannelClient* main_channel_client_get_base(MainChannelClient* mcc)
|
||||
{
|
||||
ASSERT(mcc);
|
||||
return &mcc->base;
|
||||
}
|
||||
|
||||
int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_target)
|
||||
{
|
||||
RingItem *client_link;
|
||||
|
||||
ASSERT(mig_target);
|
||||
free(main_channel->mig_target.host);
|
||||
main_channel->mig_target.host = strdup(mig_target->host);
|
||||
free(main_channel->mig_target.cert_subject);
|
||||
if (mig_target->cert_subject) {
|
||||
main_channel->mig_target.cert_subject = strdup(mig_target->cert_subject);
|
||||
}
|
||||
main_channel->mig_target.port = mig_target->port;
|
||||
main_channel->mig_target.sport = mig_target->sport;
|
||||
|
||||
main_channel->num_clients_mig_wait = 0;
|
||||
|
||||
RING_FOREACH(client_link, &main_channel->base.clients) {
|
||||
MainChannelClient * mcc = SPICE_CONTAINEROF(client_link, MainChannelClient, base.channel_link);
|
||||
if (red_channel_client_test_remote_cap(&mcc->base,
|
||||
SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE)) {
|
||||
red_channel_client_pipe_add_type(&mcc->base, SPICE_MSG_MAIN_MIGRATE_BEGIN);
|
||||
mcc->mig_wait_connect = TRUE;
|
||||
mcc->mig_connect_ok = FALSE;
|
||||
main_channel->num_clients_mig_wait++;
|
||||
}
|
||||
}
|
||||
return main_channel->num_clients_mig_wait;
|
||||
}
|
||||
|
||||
void main_channel_migrate_cancel_wait(MainChannel *main_chan)
|
||||
{
|
||||
RingItem *client_link;
|
||||
|
||||
RING_FOREACH(client_link, &main_chan->base.clients) {
|
||||
MainChannelClient *mcc;
|
||||
|
||||
mcc = SPICE_CONTAINEROF(client_link, MainChannelClient, base.channel_link);
|
||||
if (mcc->mig_wait_connect) {
|
||||
red_printf("client %p cancel wait connect", mcc->base.client);
|
||||
mcc->mig_wait_connect = FALSE;
|
||||
mcc->mig_connect_ok = FALSE;
|
||||
}
|
||||
}
|
||||
main_chan->num_clients_mig_wait = 0;
|
||||
}
|
||||
|
||||
@ -57,6 +57,8 @@ struct MainMigrateData {
|
||||
typedef struct MainChannel {
|
||||
RedChannel base;
|
||||
uint8_t recv_buf[RECEIVE_BUF_SIZE];
|
||||
RedsMigSpice mig_target; // TODO: add refs and release (afrer all clients completed migration in one way or the other?)
|
||||
int num_clients_mig_wait;
|
||||
} MainChannel;
|
||||
|
||||
|
||||
@ -80,9 +82,6 @@ void main_channel_push_init(MainChannelClient *mcc, int connection_id, int displ
|
||||
int current_mouse_mode, int is_client_mouse_allowed, int multi_media_time,
|
||||
int ram_hint);
|
||||
void main_channel_push_notify(MainChannel *main_chan, uint8_t *mess, const int mess_len);
|
||||
// TODO: consider exporting RedsMigSpice from reds.c
|
||||
void main_channel_push_migrate_begin(MainChannel *main_chan, int port, int sport, char *host,
|
||||
uint16_t cert_pub_key_type, uint32_t cert_pub_key_len, uint8_t *cert_pub_key);
|
||||
void main_channel_push_migrate(MainChannel *main_chan);
|
||||
void main_channel_push_migrate_switch(MainChannel *main_chan);
|
||||
void main_channel_push_migrate_cancel(MainChannel *main_chan);
|
||||
@ -94,5 +93,12 @@ uint32_t main_channel_client_get_link_id(MainChannelClient *mcc);
|
||||
int main_channel_client_is_low_bandwidth(MainChannelClient *mcc);
|
||||
uint64_t main_channel_client_get_bitrate_per_sec(MainChannelClient *mcc);
|
||||
int main_channel_is_connected(MainChannel *main_chan);
|
||||
RedChannelClient* main_channel_client_get_base(MainChannelClient* mcc);
|
||||
|
||||
/* semi seamless migration */
|
||||
|
||||
/* returns the number of clients that we are waiting for their connection */
|
||||
int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_target);
|
||||
void main_channel_migrate_cancel_wait(MainChannel *main_chan);
|
||||
void main_channel_migrate_complete(MainChannel *main_chan, int success);
|
||||
#endif
|
||||
|
||||
@ -450,6 +450,7 @@ struct RedClient {
|
||||
pthread_t thread_id;
|
||||
|
||||
int disconnecting;
|
||||
|
||||
};
|
||||
|
||||
RedClient *red_client_new(void);
|
||||
@ -457,7 +458,6 @@ MainChannelClient *red_client_get_main(RedClient *client);
|
||||
// main should be set once before all the other channels are created
|
||||
void red_client_set_main(RedClient *client, MainChannelClient *mcc);
|
||||
|
||||
|
||||
void red_client_migrate(RedClient *client);
|
||||
// disconnects all the client's channels (should be called from the client's thread)
|
||||
void red_client_destroy(RedClient *client);
|
||||
|
||||
151
server/reds.c
151
server/reds.c
@ -191,8 +191,6 @@ typedef struct RedsStatValue {
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct RedsMigSpice RedsMigSpice;
|
||||
|
||||
typedef struct RedsState {
|
||||
int listen_socket;
|
||||
int secure_listen_socket;
|
||||
@ -295,6 +293,7 @@ struct ChannelSecurityOptions {
|
||||
ChannelSecurityOptions *next;
|
||||
};
|
||||
|
||||
static void migrate_timeout(void *opaque);
|
||||
|
||||
static ChannelSecurityOptions *channels_security = NULL;
|
||||
static int default_channel_security =
|
||||
@ -538,6 +537,12 @@ static RedChannel *reds_find_channel(uint32_t type, uint32_t id)
|
||||
static void reds_mig_cleanup(void)
|
||||
{
|
||||
if (reds->mig_inprogress) {
|
||||
if (reds->mig_wait_connect) {
|
||||
SpiceMigrateInterface *sif;
|
||||
ASSERT(migration_interface);
|
||||
sif = SPICE_CONTAINEROF(migration_interface->base.sif, SpiceMigrateInterface, base);
|
||||
sif->migrate_connect_complete(migration_interface);
|
||||
}
|
||||
reds->mig_inprogress = FALSE;
|
||||
reds->mig_wait_connect = FALSE;
|
||||
reds->mig_wait_disconnect = FALSE;
|
||||
@ -1060,13 +1065,6 @@ void reds_on_main_migrate_connected(void)
|
||||
}
|
||||
}
|
||||
|
||||
void reds_on_main_migrate_connect_error(void)
|
||||
{
|
||||
if (reds->mig_wait_connect) {
|
||||
reds_mig_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void reds_on_main_mouse_mode_request(void *message, size_t size)
|
||||
{
|
||||
switch (((SpiceMsgcMainMouseModeRequest *)message)->mode) {
|
||||
@ -2976,18 +2974,6 @@ static void set_one_channel_security(int id, uint32_t security)
|
||||
|
||||
#define REDS_SAVE_VERSION 1
|
||||
|
||||
struct RedsMigSpice {
|
||||
char pub_key[SPICE_TICKET_PUBKEY_BYTES];
|
||||
uint32_t mig_key;
|
||||
char *host;
|
||||
char *cert_subject;
|
||||
int port;
|
||||
int sport;
|
||||
uint16_t cert_pub_key_type;
|
||||
uint32_t cert_pub_key_len;
|
||||
uint8_t* cert_pub_key;
|
||||
};
|
||||
|
||||
typedef struct RedsMigSpiceMessage {
|
||||
uint32_t connection_id;
|
||||
} RedsMigSpiceMessage;
|
||||
@ -3007,24 +2993,12 @@ void reds_mig_release(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void reds_mig_continue(void)
|
||||
{
|
||||
RedsMigSpice *s = reds->mig_spice;
|
||||
|
||||
red_printf("");
|
||||
main_channel_push_migrate_begin(reds->main_channel, s->port, s->sport,
|
||||
s->host, s->cert_pub_key_type, s->cert_pub_key_len, s->cert_pub_key);
|
||||
|
||||
reds_mig_release();
|
||||
|
||||
reds->mig_wait_connect = TRUE;
|
||||
core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
|
||||
}
|
||||
|
||||
static void reds_mig_started(void)
|
||||
{
|
||||
red_printf("");
|
||||
ASSERT(reds->mig_spice);
|
||||
|
||||
reds->mig_wait_connect = TRUE;
|
||||
reds->mig_inprogress = TRUE;
|
||||
|
||||
if (reds->listen_watch != NULL) {
|
||||
@ -3034,24 +3008,7 @@ static void reds_mig_started(void)
|
||||
if (reds->secure_listen_watch != NULL) {
|
||||
core->watch_update_mask(reds->secure_listen_watch, 0);
|
||||
}
|
||||
|
||||
if (!reds_main_channel_connected()) {
|
||||
red_printf("not connected to peer");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((SPICE_VERSION_MAJOR == 1) && (reds->peer_minor_version < 2)) {
|
||||
red_printf("minor version mismatch client %u server %u",
|
||||
reds->peer_minor_version, SPICE_VERSION_MINOR);
|
||||
goto error;
|
||||
}
|
||||
|
||||
reds_mig_continue();
|
||||
return;
|
||||
|
||||
error:
|
||||
reds_mig_release();
|
||||
reds_mig_disconnect();
|
||||
core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
|
||||
}
|
||||
|
||||
static void reds_mig_finished(int completed)
|
||||
@ -3127,11 +3084,16 @@ void reds_fill_mig_switch(SpiceMsgMainMigrationSwitchHost *migrate)
|
||||
}
|
||||
}
|
||||
|
||||
static void migrate_timout(void *opaque)
|
||||
static void migrate_timeout(void *opaque)
|
||||
{
|
||||
red_printf("");
|
||||
ASSERT(reds->mig_wait_connect || reds->mig_wait_disconnect);
|
||||
reds_mig_disconnect();
|
||||
if (reds->mig_wait_connect) {
|
||||
main_channel_migrate_cancel_wait(reds->main_channel);
|
||||
reds_mig_cleanup();
|
||||
} else {
|
||||
reds_mig_disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t reds_get_mm_time(void)
|
||||
@ -3492,7 +3454,7 @@ static int do_spice_init(SpiceCoreInterface *core_interface)
|
||||
main_dispatcher_init(core);
|
||||
ring_init(&reds->channels);
|
||||
|
||||
if (!(reds->mig_timer = core->timer_add(migrate_timout, NULL))) {
|
||||
if (!(reds->mig_timer = core->timer_add(migrate_timeout, NULL))) {
|
||||
red_error("migration timer create failed");
|
||||
}
|
||||
if (!(reds->vdi_port_write_timer = core->timer_add(vdi_port_write_retry, NULL)))
|
||||
@ -3875,33 +3837,17 @@ SPICE_GNUC_VISIBLE int spice_server_set_agent_copypaste(SpiceServer *s, int enab
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* semi-seamless client migration */
|
||||
SPICE_GNUC_VISIBLE int spice_server_migrate_connect(SpiceServer *s, const char* dest,
|
||||
int port, int secure_port,
|
||||
const char* cert_subject)
|
||||
{
|
||||
SpiceMigrateInterface *sif;
|
||||
red_printf("");
|
||||
ASSERT(migration_interface);
|
||||
ASSERT(reds == s);
|
||||
|
||||
red_printf("not implemented yet");
|
||||
sif = SPICE_CONTAINEROF(migration_interface->base.sif, SpiceMigrateInterface, base);
|
||||
sif->migrate_connect_complete(migration_interface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE int spice_server_migrate_info(SpiceServer *s, const char* dest,
|
||||
int port, int secure_port,
|
||||
const char* cert_subject)
|
||||
/* returns FALSE if info is invalid */
|
||||
static int reds_set_migration_dest_info(const char* dest,
|
||||
int port, int secure_port,
|
||||
const char* cert_subject)
|
||||
{
|
||||
RedsMigSpice *spice_migration = NULL;
|
||||
|
||||
ASSERT(reds == s);
|
||||
|
||||
if ((port == -1 && secure_port == -1) || !dest)
|
||||
return -1;
|
||||
reds_mig_release();
|
||||
if ((port == -1 && secure_port == -1) || !dest) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
spice_migration = spice_new0(RedsMigSpice, 1);
|
||||
spice_migration->port = port;
|
||||
@ -3911,12 +3857,53 @@ SPICE_GNUC_VISIBLE int spice_server_migrate_info(SpiceServer *s, const char* des
|
||||
spice_migration->cert_subject = strdup(cert_subject);
|
||||
}
|
||||
|
||||
reds_mig_release();
|
||||
reds->mig_spice = spice_migration;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* semi-seamless client migration */
|
||||
SPICE_GNUC_VISIBLE int spice_server_migrate_connect(SpiceServer *s, const char* dest,
|
||||
int port, int secure_port,
|
||||
const char* cert_subject)
|
||||
{
|
||||
SpiceMigrateInterface *sif;
|
||||
|
||||
red_printf("");
|
||||
ASSERT(migration_interface);
|
||||
ASSERT(reds == s);
|
||||
|
||||
sif = SPICE_CONTAINEROF(migration_interface->base.sif, SpiceMigrateInterface, base);
|
||||
|
||||
if (!reds_set_migration_dest_info(dest, port, secure_port, cert_subject)) {
|
||||
sif->migrate_connect_complete(migration_interface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (main_channel_migrate_connect(reds->main_channel, reds->mig_spice)) {
|
||||
reds->mig_wait_connect = TRUE;
|
||||
reds_mig_started();
|
||||
} else {
|
||||
sif->migrate_connect_complete(migration_interface);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE int spice_server_migrate_info(SpiceServer *s, const char* dest,
|
||||
int port, int secure_port,
|
||||
const char* cert_subject)
|
||||
{
|
||||
ASSERT(!migration_interface);
|
||||
ASSERT(reds == s);
|
||||
|
||||
if (!reds_set_migration_dest_info(dest, port, secure_port, cert_subject)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interface for seamless migration */
|
||||
SPICE_GNUC_VISIBLE int spice_server_migrate_start(SpiceServer *s)
|
||||
{
|
||||
ASSERT(reds == s);
|
||||
|
||||
@ -99,6 +99,13 @@ struct SpiceMigrateState {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
typedef struct RedsMigSpice {
|
||||
char *host;
|
||||
char *cert_subject;
|
||||
int port;
|
||||
int sport;
|
||||
} RedsMigSpice;
|
||||
|
||||
ssize_t reds_stream_read(RedsStream *s, void *buf, size_t nbyte);
|
||||
ssize_t reds_stream_write(RedsStream *s, const void *buf, size_t nbyte);
|
||||
ssize_t reds_stream_writev(RedsStream *s, const struct iovec *iov, int iovcnt);
|
||||
@ -134,11 +141,12 @@ int reds_num_of_clients(void);
|
||||
void reds_update_stat_value(uint32_t value);
|
||||
#endif
|
||||
|
||||
// callbacks from main channel messages
|
||||
/* callbacks from main channel messages */
|
||||
|
||||
void reds_on_main_agent_start(void);
|
||||
void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size);
|
||||
void reds_on_main_migrate_connected(void);
|
||||
void reds_on_main_migrate_connect_error(void);
|
||||
void reds_on_main_migrate_connected(void); //should be called when all the clients
|
||||
// are connected to the target
|
||||
void reds_on_main_receive_migrate_data(MainMigrateData *data, uint8_t *end);
|
||||
void reds_on_main_mouse_mode_request(void *message, size_t size);
|
||||
|
||||
|
||||
@ -167,9 +167,8 @@ channel MainChannel : BaseChannel {
|
||||
uint16 sport;
|
||||
uint32 host_size;
|
||||
uint8 *host_data[host_size] @zero_terminated @marshall @nonnull;
|
||||
pubkey_type pub_key_type;
|
||||
uint32 pub_key_size;
|
||||
uint8 *pub_key_data[pub_key_size] @zero_terminated @marshall @nonnull;
|
||||
uint32 cert_subject_size;
|
||||
uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall;
|
||||
} @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101;
|
||||
|
||||
Empty migrate_cancel;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user