1. server-side channel implementation
1. The server registers the channel.
Server channel type
enum { SPICE_CHANNEL_MAIN = 1, SPICE_CHANNEL_DISPLAY, SPICE_CHANNEL_INPUTS, SPICE_CHANNEL_CURSOR, SPICE_CHANNEL_PLAYBACK, SPICE_CHANNEL_RECORD, SPICE_CHANNEL_TUNNEL, SPICE_CHANNEL_SMARTCARD, SPICE_CHANNEL_USBREDIR, SPICE_CHANNEL_PORT, SPICE_END_CHANNEL};
The most critical data structure of the server is redsstate. Another example is spiceserver. The server maintains a global redsstate variable to store global data. The global data structure is created by qemu during coreinterface initialization and passed to libspice through the VDI interface.
A data member in redsstate is channel * channels. The server maintains a channel linked list through this variable. All channels supported by the server must be registered through reds_register_channel. Except that inputchannle is registered in spice_server_init (that is, registered during coreinterface initialization), other channels are initialized on qemu for Virtual Devices, you have registered a VDI instance by calling the spice_server_add_interface function, as shown below:
// Register in container: Register in container // spice_server_add_interface (partition) red_dispatcher_init: Register in spice_channel_display, container // container (partition) snd_attach_playback: Container // spice_server_add_interface (partition) register in snd_attach_record: spice_channel_record // spice_server_add_interface (spice_interface_net_wire) red_tunnel_attach: spice_channel_tunnel
Registering a channel is to initialize a channel object and insert it into the channels ring of redsstate for subsequent access. The specific channel structure is as follows:
struct RedChannel { uint32_t type; uint32_t id; uint32_t refs; RingItem link; // channels link for reds SpiceCoreInterface *core; int handle_acks; // RedChannel will hold only connected channel clients (logic - when pushing pipe item to all channel clients, there // is no need to go over disconnect clients) // . While client will hold the channel clients till it is destroyed // and then it will destroy them as well. // However RCC still holds a reference to the Channel. // Maybe replace these logic with ref count? // TODO: rename to 'connected_clients'? Ring clients; uint32_t clients_num; OutgoingHandlerInterface outgoing_cb; IncomingHandlerInterface incoming_cb; ChannelCbs channel_cbs; ClientCbs client_cbs; RedChannelCapabilities local_caps; uint32_t migration_flags; void *data; // TODO: when different channel_clients are in different threads from Channel -> need to protect! pthread_t thread_id;#ifdef RED_STATISTICS uint64_t *out_bytes_counter;#endif};