mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-09 05:51:00 +00:00
Avoid using global variable for channel IDs
This patch allocates VMC IDs by finding the first ID not used instead of using a global variable and incrementing the value for each channel created. This solves some potential issues: - remove the global state potentially making possible to use multiple SpiceServer on the same process; - don't potentially overflow the variable. This can happen if channels are allocated/deallocated multiple times (currently not done by Qemu). Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
parent
407ad2d63f
commit
dd871c01a8
@ -408,6 +408,38 @@ RedChannel *reds_find_channel(RedsState *reds, uint32_t type, uint32_t id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Search for first free channel id for a specific channel type.
|
||||
* Return first id free or <0 if not found. */
|
||||
int reds_get_free_channel_id(RedsState *reds, uint32_t type)
|
||||
{
|
||||
RedChannel *channel;
|
||||
|
||||
// this mark if some IDs are used.
|
||||
// The size of the array limits the possible id returned but
|
||||
// usually the IDs used for a channel type are not much.
|
||||
bool used_ids[256];
|
||||
|
||||
unsigned n;
|
||||
|
||||
// mark id used for the specific channel type
|
||||
memset(used_ids, 0, sizeof(used_ids));
|
||||
GLIST_FOREACH(reds->channels, RedChannel, channel) {
|
||||
uint32_t this_type, this_id;
|
||||
g_object_get(channel, "channel-type", &this_type, "id", &this_id, NULL);
|
||||
if (this_type == type && this_id < SPICE_N_ELEMENTS(used_ids)) {
|
||||
used_ids[this_id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// find first ID not marked as used
|
||||
for (n = 0; n < SPICE_N_ELEMENTS(used_ids); ++n) {
|
||||
if (!used_ids[n]) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void reds_mig_cleanup(RedsState *reds)
|
||||
{
|
||||
if (reds->mig_inprogress) {
|
||||
|
||||
@ -48,6 +48,7 @@ uint32_t reds_get_mm_time(void);
|
||||
void reds_register_channel(RedsState *reds, RedChannel *channel);
|
||||
void reds_unregister_channel(RedsState *reds, RedChannel *channel);
|
||||
RedChannel *reds_find_channel(RedsState *reds, uint32_t type, uint32_t id);
|
||||
int reds_get_free_channel_id(RedsState *reds, uint32_t type);
|
||||
SpiceMouseMode reds_get_mouse_mode(RedsState *reds); // used by inputs_channel
|
||||
gboolean reds_config_get_agent_mouse(const RedsState *reds); // used by inputs_channel
|
||||
int reds_has_vdagent(RedsState *reds); // used by inputs channel
|
||||
|
||||
@ -272,7 +272,6 @@ red_vmc_channel_finalize(GObject *object)
|
||||
static RedVmcChannel *red_vmc_channel_new(RedsState *reds, uint8_t channel_type)
|
||||
{
|
||||
GType gtype = G_TYPE_NONE;
|
||||
static uint8_t id[SPICE_END_CHANNEL] = { 0, };
|
||||
|
||||
switch (channel_type) {
|
||||
case SPICE_CHANNEL_USBREDIR:
|
||||
@ -288,11 +287,18 @@ static RedVmcChannel *red_vmc_channel_new(RedsState *reds, uint8_t channel_type)
|
||||
g_error("Unsupported channel_type for red_vmc_channel_new(): %u", channel_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int id = reds_get_free_channel_id(reds, channel_type);
|
||||
if (id < 0) {
|
||||
g_warning("Free ID not found creating new VMC channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_object_new(gtype,
|
||||
"spice-server", reds,
|
||||
"core-interface", reds_get_core_interface(reds),
|
||||
"channel-type", channel_type,
|
||||
"id", id[channel_type]++,
|
||||
"id", id,
|
||||
"handle-acks", FALSE,
|
||||
"migration-flags",
|
||||
(SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user