static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc) { SpiceVmcState *state; SpiceCharDeviceInstance *sin; SpiceCharDeviceInterface *sif; if (!rcc) { return; } state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel); sin = state->chardev_sin; sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base); if (state->chardev_st) { if (spice_char_device_client_exists(state->chardev_st, rcc->client)) { spice_char_device_client_remove(state->chardev_st, rcc->client); } else { spice_printerr("client %p have already been removed from char dev %p", rcc->client, state->chardev_st); } } /* Don't destroy the rcc if it is already being destroyed, as then red_client_destroy/red_channel_client_destroy will already do this! */ if (!rcc->destroying) red_channel_client_destroy(rcc); state->rcc = NULL; if (sif->state) { sif->state(sin, 0); } }
static void spicevmc_connect(RedChannel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) { RedChannelClient *rcc; SpiceVmcState *state; SpiceCharDeviceInstance *sin; SpiceCharDeviceInterface *sif; state = SPICE_CONTAINEROF(channel, SpiceVmcState, channel); sin = state->chardev_sin; sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base); if (state->rcc) { spice_printerr("channel client %d:%d (%p) already connected, refusing second connection", channel->type, channel->id, state->rcc); // TODO: notify client in advance about the in use channel using // SPICE_MSG_MAIN_CHANNEL_IN_USE (for example) reds_stream_free(stream); return; } rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream, FALSE, num_common_caps, common_caps, num_caps, caps); if (!rcc) { return; } state->rcc = rcc; red_channel_client_ack_zero_messages_window(rcc); if (strcmp(sin->subtype, "port") == 0) { spicevmc_port_send_init(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); } }