diff --git a/server/cursor-channel-client.h b/server/cursor-channel-client.h index 56b3b312..4deae535 100644 --- a/server/cursor-channel-client.h +++ b/server/cursor-channel-client.h @@ -75,6 +75,12 @@ enum { RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, }; +/** + * Migrate a client channel from a CursorChannel. + * This is the equivalent of RedChannel client migrate callback. + */ +void cursor_channel_client_migrate(RedChannelClient *client); + G_END_DECLS #endif /* CURSOR_CHANNEL_CLIENT_H_ */ diff --git a/server/cursor-channel.c b/server/cursor-channel.c index e8af01b0..d936b791 100644 --- a/server/cursor-channel.c +++ b/server/cursor-channel.c @@ -335,9 +335,12 @@ void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode) cursor->mouse_mode = mode; } -void cursor_channel_connect(CursorChannel *cursor, RedClient *client, RedStream *stream, - int migrate, - RedChannelCapabilities *caps) +/** + * Connect a new client to CursorChannel. + */ +static void +cursor_channel_connect(CursorChannel *cursor, RedClient *client, RedStream *stream, + int migrate, RedChannelCapabilities *caps) { CursorChannelClient *ccc; @@ -392,6 +395,10 @@ cursor_channel_class_init(CursorChannelClass *klass) channel_class->handle_message = red_channel_client_handle_message; channel_class->send_item = cursor_channel_send_item; + + // client callbacks + channel_class->connect = (channel_client_connect_proc) cursor_channel_connect; + channel_class->migrate = cursor_channel_client_migrate; } static void diff --git a/server/cursor-channel.h b/server/cursor-channel.h index 332aa987..dc48279a 100644 --- a/server/cursor-channel.h +++ b/server/cursor-channel.h @@ -60,21 +60,6 @@ void cursor_channel_do_init (CursorChannel *cursor); void cursor_channel_process_cmd (CursorChannel *cursor, RedCursorCmd *cursor_cmd); void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode); -/** - * Connect a new client to CursorChannel. - */ -void cursor_channel_connect (CursorChannel *cursor, RedClient *client, - RedStream *stream, - int migrate, - RedChannelCapabilities *caps); - -/** - * Migrate a client channel from a CursorChannel. - * This is the equivalent of RedChannel client migrate callback. - * See comment on cursor_channel_new. - */ -void cursor_channel_client_migrate(RedChannelClient *client); - G_END_DECLS #endif /* CURSOR_CHANNEL_H_ */ diff --git a/server/display-channel.c b/server/display-channel.c index e9368668..c2129c71 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -26,6 +26,12 @@ G_DEFINE_TYPE(DisplayChannel, display_channel, TYPE_COMMON_GRAPHICS_CHANNEL) +static void display_channel_connect(RedChannel *channel, RedClient *client, + RedStream *stream, int migration, + RedChannelCapabilities *caps); +static void display_channel_disconnect(RedChannelClient *rcc); +static void display_channel_migrate(RedChannelClient *rcc); + enum { PROP0, PROP_N_SURFACES, @@ -2500,6 +2506,11 @@ display_channel_class_init(DisplayChannelClass *klass) channel_class->handle_migrate_data = handle_migrate_data; channel_class->handle_migrate_data_get_serial = handle_migrate_data_get_serial; + // client callbacks + channel_class->connect = display_channel_connect; + channel_class->disconnect = display_channel_disconnect; + channel_class->migrate = display_channel_migrate; + g_object_class_install_property(object_class, PROP_N_SURFACES, g_param_spec_uint("n-surfaces", @@ -2590,7 +2601,7 @@ void display_channel_update_qxl_running(DisplayChannel *display, bool running) } } -void +static void display_channel_connect(RedChannel *channel, RedClient *client, RedStream *stream, int migration, RedChannelCapabilities *caps) @@ -2613,7 +2624,7 @@ display_channel_connect(RedChannel *channel, RedClient *client, dcc_start(dcc); } -void display_channel_disconnect(RedChannelClient *rcc) +static void display_channel_disconnect(RedChannelClient *rcc) { DisplayChannel *display = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc)); @@ -2640,7 +2651,7 @@ static void red_migrate_display(DisplayChannel *display, RedChannelClient *rcc) } } -void display_channel_migrate(RedChannelClient *rcc) +static void display_channel_migrate(RedChannelClient *rcc) { DisplayChannel *display = DISPLAY_CHANNEL(red_channel_client_get_channel(rcc)); red_migrate_display(display, rcc); diff --git a/server/display-channel.h b/server/display-channel.h index 7dfedd75..8dfdf523 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -159,11 +159,6 @@ void display_channel_reset_image_cache(DisplayChannel *self); void display_channel_debug_oom(DisplayChannel *display, const char *msg); void display_channel_update_qxl_running(DisplayChannel *display, bool running); -void display_channel_connect(RedChannel *channel, RedClient *client, - RedStream *stream, int migration, - RedChannelCapabilities *caps); -void display_channel_disconnect(RedChannelClient *rcc); -void display_channel_migrate(RedChannelClient *rcc); G_END_DECLS diff --git a/server/inputs-channel.c b/server/inputs-channel.c index a7df62e2..eff5421a 100644 --- a/server/inputs-channel.c +++ b/server/inputs-channel.c @@ -542,17 +542,12 @@ InputsChannel* inputs_channel_new(RedsState *reds) static void inputs_channel_constructed(GObject *object) { - ClientCbs client_cbs = { NULL, }; InputsChannel *self = INPUTS_CHANNEL(object); RedsState *reds = red_channel_get_server(RED_CHANNEL(self)); SpiceCoreInterfaceInternal *core = red_channel_get_core_interface(RED_CHANNEL(self)); G_OBJECT_CLASS(inputs_channel_parent_class)->constructed(object); - client_cbs.connect = inputs_connect; - client_cbs.migrate = inputs_migrate; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); - red_channel_set_cap(RED_CHANNEL(self), SPICE_INPUTS_CAP_KEY_SCANCODE); reds_register_channel(reds, RED_CHANNEL(self)); @@ -596,6 +591,10 @@ inputs_channel_class_init(InputsChannelClass *klass) channel_class->send_item = inputs_channel_send_item; channel_class->handle_migrate_data = inputs_channel_handle_migrate_data; channel_class->handle_migrate_flush_mark = inputs_channel_handle_migrate_flush_mark; + + // client callbacks + channel_class->connect = inputs_connect; + channel_class->migrate = inputs_migrate; } static SpiceKbdInstance* inputs_channel_get_keyboard(InputsChannel *inputs) diff --git a/server/main-channel.c b/server/main-channel.c index f866fb4a..a48e74be 100644 --- a/server/main-channel.c +++ b/server/main-channel.c @@ -264,15 +264,11 @@ static void main_channel_constructed(GObject *object) { MainChannel *self = MAIN_CHANNEL(object); - ClientCbs client_cbs = { NULL, }; G_OBJECT_CLASS(main_channel_parent_class)->constructed(object); red_channel_set_cap(RED_CHANNEL(self), SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE); red_channel_set_cap(RED_CHANNEL(self), SPICE_MAIN_CAP_SEAMLESS_MIGRATE); - - client_cbs.migrate = main_channel_client_migrate; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); } static void @@ -295,6 +291,9 @@ main_channel_class_init(MainChannelClass *klass) channel_class->send_item = main_channel_client_send_item; channel_class->handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark; channel_class->handle_migrate_data = main_channel_handle_migrate_data; + + // client callbacks + channel_class->migrate = main_channel_client_migrate; } static int main_channel_connect_semi_seamless(MainChannel *main_channel) diff --git a/server/red-channel.c b/server/red-channel.c index 8d4992fa..121c7e47 100644 --- a/server/red-channel.c +++ b/server/red-channel.c @@ -86,7 +86,6 @@ struct RedChannelPrivate RedChannelCapabilities local_caps; uint32_t migration_flags; - ClientCbs client_cbs; // TODO: when different channel_clients are in different threads // from Channel -> need to protect! pthread_t thread_id; @@ -302,6 +301,10 @@ red_channel_class_init(RedChannelClass *klass) | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property(object_class, PROP_DISPATCHER, spec); + + klass->connect = red_channel_client_default_connect; + klass->disconnect = red_channel_client_default_disconnect; + klass->migrate = red_channel_client_default_migrate; } static void @@ -311,10 +314,6 @@ red_channel_init(RedChannel *self) red_channel_set_common_cap(self, SPICE_COMMON_CAP_MINI_HEADER); self->priv->thread_id = pthread_self(); - - self->priv->client_cbs.connect = red_channel_client_default_connect; - self->priv->client_cbs.disconnect = red_channel_client_default_disconnect; - self->priv->client_cbs.migrate = red_channel_client_default_migrate; } // utility to avoid possible invalid function cast @@ -380,20 +379,6 @@ const RedStatNode *red_channel_get_stat_node(RedChannel *channel) return &channel->priv->stat; } -void red_channel_register_client_cbs(RedChannel *channel, const ClientCbs *client_cbs) -{ - spice_assert(client_cbs->connect || channel->priv->type == SPICE_CHANNEL_MAIN); - channel->priv->client_cbs.connect = client_cbs->connect; - - if (client_cbs->disconnect) { - channel->priv->client_cbs.disconnect = client_cbs->disconnect; - } - - if (client_cbs->migrate) { - channel->priv->client_cbs.migrate = client_cbs->migrate; - } -} - static void add_capability(uint32_t **caps, int *num_caps, uint32_t cap) { int nbefore, n; @@ -518,9 +503,9 @@ static void handle_dispatcher_connect(void *opaque, void *payload) { RedMessageConnect *msg = payload; RedChannel *channel = msg->channel; + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); - channel->priv->client_cbs.connect(channel, msg->client, msg->stream, - msg->migration, &msg->caps); + klass->connect(channel, msg->client, msg->stream, msg->migration, &msg->caps); g_object_unref(msg->client); red_channel_capabilities_reset(&msg->caps); } @@ -531,7 +516,8 @@ void red_channel_connect(RedChannel *channel, RedClient *client, { if (channel->priv->dispatcher == NULL || pthread_equal(pthread_self(), channel->priv->thread_id)) { - channel->priv->client_cbs.connect(channel, client, stream, migration, caps); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + klass->connect(channel, client, stream, migration, caps); return; } @@ -759,8 +745,9 @@ static void handle_dispatcher_migrate(void *opaque, void *payload) { RedMessageMigrate *msg = payload; RedChannel *channel = red_channel_client_get_channel(msg->rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); - channel->priv->client_cbs.migrate(msg->rcc); + klass->migrate(msg->rcc); g_object_unref(msg->rcc); } @@ -768,7 +755,8 @@ void red_channel_migrate_client(RedChannel *channel, RedChannelClient *rcc) { if (channel->priv->dispatcher == NULL || pthread_equal(pthread_self(), channel->priv->thread_id)) { - channel->priv->client_cbs.migrate(rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + klass->migrate(rcc); return; } @@ -785,15 +773,17 @@ static void handle_dispatcher_disconnect(void *opaque, void *payload) { RedMessageDisconnect *msg = payload; RedChannel *channel = red_channel_client_get_channel(msg->rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); - channel->priv->client_cbs.disconnect(msg->rcc); + klass->disconnect(msg->rcc); } void red_channel_disconnect_client(RedChannel *channel, RedChannelClient *rcc) { if (channel->priv->dispatcher == NULL || pthread_equal(pthread_self(), channel->priv->thread_id)) { - channel->priv->client_cbs.disconnect(rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + klass->disconnect(rcc); return; } diff --git a/server/red-channel.h b/server/red-channel.h index bb3a95e8..4bfd81ee 100644 --- a/server/red-channel.h +++ b/server/red-channel.h @@ -63,16 +63,6 @@ typedef void (*channel_client_disconnect_proc)(RedChannelClient *base); typedef void (*channel_client_migrate_proc)(RedChannelClient *base); -/* - * callbacks that are triggered from client events. - * They should be called from the thread that handles the RedClient - */ -typedef struct { - channel_client_connect_proc connect; - channel_client_disconnect_proc disconnect; - channel_client_migrate_proc migrate; -} ClientCbs; - static inline gboolean test_capability(const uint32_t *caps, int num_caps, uint32_t cap) { return VD_AGENT_HAS_CAPABILITY(caps, num_caps, cap); @@ -107,6 +97,14 @@ struct RedChannelClass channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark; channel_handle_migrate_data_proc handle_migrate_data; channel_handle_migrate_data_get_serial_proc handle_migrate_data_get_serial; + + /* + * callbacks that are triggered from client events. + * They should be called from the thread that handles the RedClient + */ + channel_client_connect_proc connect; + channel_client_disconnect_proc disconnect; + channel_client_migrate_proc migrate; }; #define FOREACH_CLIENT(_channel, _data) \ @@ -122,7 +120,6 @@ void red_channel_remove_client(RedChannel *channel, RedChannelClient *rcc); void red_channel_init_stat_node(RedChannel *channel, const RedStatNode *parent, const char *name); -void red_channel_register_client_cbs(RedChannel *channel, const ClientCbs *client_cbs); // caps are freed when the channel is destroyed void red_channel_set_common_cap(RedChannel *channel, uint32_t cap); void red_channel_set_cap(RedChannel *channel, uint32_t cap); diff --git a/server/red-stream-device.c b/server/red-stream-device.c index cf5a6e9a..b4c32f71 100644 --- a/server/red-stream-device.c +++ b/server/red-stream-device.c @@ -695,12 +695,7 @@ stream_device_create_channel(StreamDevice *dev) g_return_if_fail(id >= 0); StreamChannel *stream_channel = stream_channel_new(reds, id); - CursorChannel *cursor_channel = cursor_channel_new(reds, id, core, NULL); - ClientCbs client_cbs = { NULL, }; - client_cbs.connect = (channel_client_connect_proc) cursor_channel_connect; - client_cbs.migrate = cursor_channel_client_migrate; - red_channel_register_client_cbs(RED_CHANNEL(cursor_channel), &client_cbs); dev->stream_channel = stream_channel; dev->cursor_channel = cursor_channel; diff --git a/server/red-worker.c b/server/red-worker.c index d6b69f29..129f9f93 100644 --- a/server/red-worker.c +++ b/server/red-worker.c @@ -1144,12 +1144,6 @@ RedWorker* red_worker_new(QXLInstance *qxl) channel = RED_CHANNEL(worker->cursor_channel); red_channel_init_stat_node(channel, &worker->stat, "cursor_channel"); - ClientCbs client_cursor_cbs = { NULL, }; - client_cursor_cbs.connect = (channel_client_connect_proc) cursor_channel_connect; - client_cursor_cbs.disconnect = NULL; - client_cursor_cbs.migrate = cursor_channel_client_migrate; - red_channel_register_client_cbs(channel, &client_cursor_cbs); - // TODO: handle seamless migration. Temp, setting migrate to FALSE worker->display_channel = display_channel_new(reds, qxl, &worker->core, dispatcher, FALSE, @@ -1159,12 +1153,6 @@ RedWorker* red_worker_new(QXLInstance *qxl) channel = RED_CHANNEL(worker->display_channel); red_channel_init_stat_node(channel, &worker->stat, "display_channel"); - ClientCbs client_display_cbs = { NULL, }; - client_display_cbs.connect = display_channel_connect; - client_display_cbs.disconnect = display_channel_disconnect; - client_display_cbs.migrate = display_channel_migrate; - red_channel_register_client_cbs(channel, &client_display_cbs); - return worker; } diff --git a/server/smartcard.c b/server/smartcard.c index 9ccfbc6b..e3e746ca 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -535,13 +535,9 @@ red_smartcard_channel_constructed(GObject *object) { RedSmartcardChannel *self = RED_SMARTCARD_CHANNEL(object); RedsState *reds = red_channel_get_server(RED_CHANNEL(self)); - ClientCbs client_cbs = { NULL, }; G_OBJECT_CLASS(red_smartcard_channel_parent_class)->constructed(object); - client_cbs.connect = smartcard_connect_client; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); - reds_register_channel(reds, RED_CHANNEL(self)); } @@ -559,6 +555,8 @@ red_smartcard_channel_class_init(RedSmartcardChannelClass *klass) channel_class->handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark; channel_class->handle_migrate_data = smartcard_channel_client_handle_migrate_data; + // client callbacks + channel_class->connect = smartcard_connect_client; } static void smartcard_init(RedsState *reds) diff --git a/server/sound.c b/server/sound.c index 44b27dec..167f68c5 100644 --- a/server/sound.c +++ b/server/sound.c @@ -1377,16 +1377,11 @@ playback_channel_init(PlaybackChannel *self) static void playback_channel_constructed(GObject *object) { - ClientCbs client_cbs = { NULL, }; SndChannel *self = SND_CHANNEL(object); RedsState *reds = red_channel_get_server(RED_CHANNEL(self)); G_OBJECT_CLASS(playback_channel_parent_class)->constructed(object); - client_cbs.connect = snd_set_playback_peer; - client_cbs.migrate = snd_migrate_channel_client; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); - if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) { red_channel_set_cap(RED_CHANNEL(self), SPICE_PLAYBACK_CAP_CELT_0_5_1); } @@ -1407,6 +1402,10 @@ playback_channel_class_init(PlaybackChannelClass *klass) channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_PLAYBACK, NULL); channel_class->handle_message = red_channel_client_handle_message; channel_class->send_item = playback_channel_send_item; + + // client callbacks + channel_class->connect = snd_set_playback_peer; + channel_class->migrate = snd_migrate_channel_client; } void snd_attach_playback(RedsState *reds, SpicePlaybackInstance *sin) @@ -1427,16 +1426,11 @@ record_channel_init(RecordChannel *self) static void record_channel_constructed(GObject *object) { - ClientCbs client_cbs = { NULL, }; SndChannel *self = SND_CHANNEL(object); RedsState *reds = red_channel_get_server(RED_CHANNEL(self)); G_OBJECT_CLASS(record_channel_parent_class)->constructed(object); - client_cbs.connect = snd_set_record_peer; - client_cbs.migrate = snd_migrate_channel_client; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); - if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) { red_channel_set_cap(RED_CHANNEL(self), SPICE_RECORD_CAP_CELT_0_5_1); } @@ -1457,6 +1451,10 @@ record_channel_class_init(RecordChannelClass *klass) channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_RECORD, NULL); channel_class->handle_message = record_channel_handle_message; channel_class->send_item = record_channel_send_item; + + // client callbacks + channel_class->connect = snd_set_record_peer; + channel_class->migrate = snd_migrate_channel_client; } void snd_attach_record(RedsState *reds, SpiceRecordInstance *sin) diff --git a/server/spicevmc.c b/server/spicevmc.c index 51550c1a..d094166e 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -185,14 +185,10 @@ static void red_vmc_channel_constructed(GObject *object) { RedVmcChannel *self = RED_VMC_CHANNEL(object); - ClientCbs client_cbs = { NULL, }; RedsState *reds = red_channel_get_server(RED_CHANNEL(self)); G_OBJECT_CLASS(red_vmc_channel_parent_class)->constructed(object); - client_cbs.connect = spicevmc_connect; - red_channel_register_client_cbs(RED_CHANNEL(self), &client_cbs); - red_channel_init_stat_node(RED_CHANNEL(self), NULL, "spicevmc"); const RedStatNode *stat = red_channel_get_stat_node(RED_CHANNEL(self)); stat_init_counter(&self->in_data, reds, stat, "in_data", TRUE); @@ -723,6 +719,9 @@ red_vmc_channel_class_init(RedVmcChannelClass *klass) channel_class->send_item = spicevmc_red_channel_send_item; channel_class->handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark; channel_class->handle_migrate_data = spicevmc_channel_client_handle_migrate_data; + + // client callbacks + channel_class->connect = spicevmc_connect; } static void diff --git a/server/stream-channel.c b/server/stream-channel.c index c38ee043..ed844d6d 100644 --- a/server/stream-channel.c +++ b/server/stream-channel.c @@ -443,15 +443,11 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedStream static void stream_channel_constructed(GObject *object) { - ClientCbs client_cbs = { NULL, }; RedChannel *red_channel = RED_CHANNEL(object); RedsState *reds = red_channel_get_server(red_channel); G_OBJECT_CLASS(stream_channel_parent_class)->constructed(object); - client_cbs.connect = stream_channel_connect; - red_channel_register_client_cbs(red_channel, &client_cbs); - red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_STREAM_REPORT); @@ -470,6 +466,7 @@ stream_channel_class_init(StreamChannelClass *klass) channel_class->handle_message = handle_message; channel_class->send_item = stream_channel_send_item; + channel_class->connect = stream_channel_connect; } static void diff --git a/server/tests/test-channel.c b/server/tests/test-channel.c index 1c9148df..9700e31c 100644 --- a/server/tests/test-channel.c +++ b/server/tests/test-channel.c @@ -105,25 +105,14 @@ test_connect_client(RedChannel *channel, RedClient *client, RedStream *stream, } } -static void -red_test_channel_constructed(GObject *object) -{ - G_OBJECT_CLASS(red_test_channel_parent_class)->constructed(object); - - ClientCbs client_cbs = { .connect = test_connect_client, }; - red_channel_register_client_cbs(RED_CHANNEL(object), &client_cbs); -} - static void red_test_channel_class_init(RedTestChannelClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS(klass); - object_class->constructed = red_test_channel_constructed; - RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass); channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_PORT, NULL); channel_class->handle_message = red_channel_client_handle_message; channel_class->send_item = test_channel_send_item; + channel_class->connect = test_connect_client; } static uint8_t *