mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-09 01:06:58 +00:00
char_device: don't connect a migrated client if the state of the device might have changed since it was created
If reading/writing from the device have occured before migration data has arrived, the migration data might no longer be relvant, and we disconnect the client.
This commit is contained in:
parent
a180fc5e0b
commit
9c6a49c364
@ -681,20 +681,25 @@ void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev)
|
||||
spice_char_device_state_unref(char_dev);
|
||||
}
|
||||
|
||||
void spice_char_device_client_add(SpiceCharDeviceState *dev,
|
||||
RedClient *client,
|
||||
int do_flow_control,
|
||||
uint32_t max_send_queue_size,
|
||||
uint32_t num_client_tokens,
|
||||
uint32_t num_send_tokens,
|
||||
int wait_for_migrate_data)
|
||||
int spice_char_device_client_add(SpiceCharDeviceState *dev,
|
||||
RedClient *client,
|
||||
int do_flow_control,
|
||||
uint32_t max_send_queue_size,
|
||||
uint32_t num_client_tokens,
|
||||
uint32_t num_send_tokens,
|
||||
int wait_for_migrate_data)
|
||||
{
|
||||
SpiceCharDeviceClientState *dev_client;
|
||||
|
||||
spice_assert(dev);
|
||||
spice_assert(client);
|
||||
|
||||
spice_assert(!wait_for_migrate_data || (dev->num_clients == 0 && !dev->active));
|
||||
if (wait_for_migrate_data && (dev->num_clients > 0 || dev->active)) {
|
||||
spice_warning("can't restore device %p from migration data. The device "
|
||||
"has already been active", dev);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dev->wait_for_migrate_data = wait_for_migrate_data;
|
||||
|
||||
spice_debug("dev_state %p client %p", dev, client);
|
||||
@ -721,6 +726,7 @@ void spice_char_device_client_add(SpiceCharDeviceState *dev,
|
||||
dev->num_clients++;
|
||||
/* Now that we have a client, forward any pending device data */
|
||||
spice_char_device_wakeup(dev);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void spice_char_device_client_remove(SpiceCharDeviceState *dev,
|
||||
|
||||
@ -148,13 +148,13 @@ void spice_char_device_reset(SpiceCharDeviceState *dev);
|
||||
|
||||
/* max_send_queue_size = how many messages we can read from the device and enqueue for this client,
|
||||
* when we have tokens for other clients and no tokens for this one */
|
||||
void spice_char_device_client_add(SpiceCharDeviceState *dev,
|
||||
RedClient *client,
|
||||
int do_flow_control,
|
||||
uint32_t max_send_queue_size,
|
||||
uint32_t num_client_tokens,
|
||||
uint32_t num_send_tokens,
|
||||
int wait_for_migrate_data);
|
||||
int spice_char_device_client_add(SpiceCharDeviceState *dev,
|
||||
RedClient *client,
|
||||
int do_flow_control,
|
||||
uint32_t max_send_queue_size,
|
||||
uint32_t num_client_tokens,
|
||||
uint32_t num_send_tokens,
|
||||
int wait_for_migrate_data);
|
||||
|
||||
void spice_char_device_client_remove(SpiceCharDeviceState *dev,
|
||||
RedClient *client);
|
||||
|
||||
@ -1111,13 +1111,21 @@ void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens)
|
||||
* flow control, but will have no other problem.
|
||||
*/
|
||||
if (!spice_char_device_client_exists(dev_state, rcc->client)) {
|
||||
spice_char_device_client_add(dev_state,
|
||||
rcc->client,
|
||||
TRUE, /* flow control */
|
||||
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
|
||||
REDS_AGENT_WINDOW_SIZE,
|
||||
num_tokens,
|
||||
red_channel_client_waits_for_migrate_data(rcc));
|
||||
int client_added;
|
||||
|
||||
client_added = spice_char_device_client_add(dev_state,
|
||||
rcc->client,
|
||||
TRUE, /* flow control */
|
||||
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
|
||||
REDS_AGENT_WINDOW_SIZE,
|
||||
num_tokens,
|
||||
red_channel_client_waits_for_migrate_data(rcc));
|
||||
|
||||
if (!client_added) {
|
||||
spice_warning("failed to add client to agent");
|
||||
reds_client_disconnect(rcc->client);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
spice_char_device_send_to_client_tokens_set(dev_state,
|
||||
rcc->client,
|
||||
@ -3580,13 +3588,21 @@ static SpiceCharDeviceState *attach_to_red_agent(SpiceCharDeviceInstance *sin)
|
||||
} else {
|
||||
spice_debug("waiting for migration data");
|
||||
if (!spice_char_device_client_exists(reds->agent_state.base, reds_get_client())) {
|
||||
spice_char_device_client_add(reds->agent_state.base,
|
||||
reds_get_client(),
|
||||
TRUE, /* flow control */
|
||||
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
|
||||
REDS_AGENT_WINDOW_SIZE,
|
||||
~0,
|
||||
TRUE);
|
||||
int client_added;
|
||||
|
||||
client_added = spice_char_device_client_add(reds->agent_state.base,
|
||||
reds_get_client(),
|
||||
TRUE, /* flow control */
|
||||
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
|
||||
REDS_AGENT_WINDOW_SIZE,
|
||||
~0,
|
||||
TRUE);
|
||||
|
||||
if (!client_added) {
|
||||
spice_warning("failed to add client to agent");
|
||||
reds_disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return state->base;
|
||||
|
||||
@ -339,17 +339,25 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de
|
||||
SmartCardChannelClient *scc)
|
||||
{
|
||||
SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st);
|
||||
int client_added;
|
||||
|
||||
spice_assert(!scc->smartcard_state && !st->scc);
|
||||
st->scc = scc;
|
||||
spice_char_device_client_add(st->chardev_st,
|
||||
scc->base.client,
|
||||
FALSE, /* no flow control yet */
|
||||
0, /* send queue size */
|
||||
~0,
|
||||
~0,
|
||||
red_channel_client_waits_for_migrate_data(&scc->base));
|
||||
scc->smartcard_state = st;
|
||||
client_added = spice_char_device_client_add(st->chardev_st,
|
||||
scc->base.client,
|
||||
FALSE, /* no flow control yet */
|
||||
0, /* send queue size */
|
||||
~0,
|
||||
~0,
|
||||
red_channel_client_waits_for_migrate_data(
|
||||
&scc->base));
|
||||
if (!client_added) {
|
||||
spice_warning("failed");
|
||||
st->scc = NULL;
|
||||
scc->smartcard_state = NULL;
|
||||
red_channel_client_disconnect(&scc->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void smartcard_char_device_notify_reader_remove(SmartCardDeviceState *st)
|
||||
|
||||
@ -384,8 +384,12 @@ static void spicevmc_connect(RedChannel *channel, RedClient *client,
|
||||
state->rcc = rcc;
|
||||
red_channel_client_ack_zero_messages_window(rcc);
|
||||
|
||||
spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0,
|
||||
red_channel_client_waits_for_migrate_data(rcc));
|
||||
if (!spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0,
|
||||
red_channel_client_waits_for_migrate_data(rcc))) {
|
||||
spice_warning("failed to add client to spicevmc");
|
||||
red_channel_client_disconnect(rcc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sif->state) {
|
||||
sif->state(sin, 1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user