These client callbacks really make more sense as virtual functions of the channel class. We never set different callbacks for different objects of the same class, so there's no need to be able to register e.g. different callbacks for different DisplayChannels. In the process, the signature for 'disconnect' and 'migrate' were changed slightly to provide a 'self' pointer to the channel as the first argument. Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> --- server/cursor-channel.c | 26 ++++++--------------- server/display-channel.c | 18 ++++++--------- server/inputs-channel.c | 11 ++++----- server/main-channel-client.c | 8 ------- server/main-channel-client.h | 1 - server/main-channel.c | 13 +++++++---- server/red-channel.c | 54 +++++++++++++++++--------------------------- server/red-channel.h | 25 +++++++++----------- server/smartcard.c | 6 ++--- server/sound.c | 21 ++++++++--------- server/spicevmc.c | 7 +++--- 11 files changed, 74 insertions(+), 116 deletions(-) diff --git a/server/cursor-channel.c b/server/cursor-channel.c index 02a9fe3a1..d3c1dcc71 100644 --- a/server/cursor-channel.c +++ b/server/cursor-channel.c @@ -454,12 +454,11 @@ static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, Reds &payload); } -static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc) +static void red_qxl_disconnect_cursor_peer(RedChannel *channel, RedChannelClient *rcc) { RedWorkerMessageCursorDisconnect payload; QXLInstance *qxl; Dispatcher *dispatcher; - RedChannel *channel = red_channel_client_get_channel(rcc); if (!channel) { return; @@ -475,12 +474,11 @@ static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc) &payload); } -static void red_qxl_cursor_migrate(RedChannelClient *rcc) +static void red_qxl_cursor_migrate(RedChannel *channel, RedChannelClient *rcc) { RedWorkerMessageCursorMigrate payload; QXLInstance *qxl; Dispatcher *dispatcher; - RedChannel *channel = red_channel_client_get_channel(rcc); uint32_t type, id; if (!channel) { @@ -497,26 +495,11 @@ static void red_qxl_cursor_migrate(RedChannelClient *rcc) } static void -cursor_channel_constructed(GObject *object) -{ - RedChannel *channel = RED_CHANNEL(object); - ClientCbs client_cbs = { NULL, }; - - G_OBJECT_CLASS(cursor_channel_parent_class)->constructed(object); - - client_cbs.connect = red_qxl_set_cursor_peer; - client_cbs.disconnect = red_qxl_disconnect_cursor_peer; - client_cbs.migrate = red_qxl_cursor_migrate; - red_channel_register_client_cbs(channel, &client_cbs, NULL); -} - -static void cursor_channel_class_init(CursorChannelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass); - object_class->constructed = cursor_channel_constructed; object_class->finalize = cursor_channel_finalize; channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL); @@ -524,6 +507,11 @@ cursor_channel_class_init(CursorChannelClass *klass) channel_class->on_disconnect = cursor_channel_client_on_disconnect; channel_class->send_item = cursor_channel_send_item; + + /* client cbs */ + channel_class->connect = red_qxl_set_cursor_peer; + channel_class->disconnect = red_qxl_disconnect_cursor_peer; + channel_class->migrate = red_qxl_cursor_migrate; } static void diff --git a/server/display-channel.c b/server/display-channel.c index cccf1dea9..a55b857d6 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -2310,12 +2310,11 @@ static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client, &payload); } -static void red_qxl_disconnect_display_peer(RedChannelClient *rcc) +static void red_qxl_disconnect_display_peer(RedChannel *channel, RedChannelClient *rcc) { RedWorkerMessageDisplayDisconnect payload; QXLInstance *qxl; Dispatcher *dispatcher; - RedChannel *channel = red_channel_client_get_channel(rcc); if (!channel) { return; @@ -2334,12 +2333,11 @@ static void red_qxl_disconnect_display_peer(RedChannelClient *rcc) &payload); } -static void red_qxl_display_migrate(RedChannelClient *rcc) +static void red_qxl_display_migrate(RedChannel *channel, RedChannelClient *rcc) { RedWorkerMessageDisplayMigrate payload; QXLInstance *qxl; Dispatcher *dispatcher; - RedChannel *channel = red_channel_client_get_channel(rcc); uint32_t type, id; if (!channel) { @@ -2362,7 +2360,6 @@ display_channel_constructed(GObject *object) { DisplayChannel *self = DISPLAY_CHANNEL(object); RedChannel *channel = RED_CHANNEL(self); - ClientCbs client_cbs = { NULL, }; G_OBJECT_CLASS(display_channel_parent_class)->constructed(object); @@ -2389,12 +2386,6 @@ display_channel_constructed(GObject *object) red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION); red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE); red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT); - - client_cbs.connect = red_qxl_set_display_peer; - client_cbs.disconnect = red_qxl_disconnect_display_peer; - client_cbs.migrate = red_qxl_display_migrate; - - red_channel_register_client_cbs(channel, &client_cbs, NULL); } void display_channel_process_surface_cmd(DisplayChannel *display, @@ -2589,6 +2580,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 cbs */ + channel_class->connect = red_qxl_set_display_peer; + channel_class->disconnect = red_qxl_disconnect_display_peer; + channel_class->migrate = red_qxl_display_migrate; + g_object_class_install_property(object_class, PROP_N_SURFACES, g_param_spec_uint("n-surfaces", diff --git a/server/inputs-channel.c b/server/inputs-channel.c index 943c69d6c..51dec304f 100644 --- a/server/inputs-channel.c +++ b/server/inputs-channel.c @@ -471,9 +471,9 @@ static void inputs_connect(RedChannel *channel, RedClient *client, inputs_pipe_add_init(rcc); } -static void inputs_migrate(RedChannelClient *rcc) +static void inputs_migrate(RedChannel *self, RedChannelClient *rcc) { - InputsChannel *inputs = INPUTS_CHANNEL(red_channel_client_get_channel(rcc)); + InputsChannel *inputs = INPUTS_CHANNEL(self); inputs->src_during_migrate = TRUE; red_channel_client_default_migrate(rcc); } @@ -545,16 +545,11 @@ 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)); 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, NULL); - red_channel_set_cap(RED_CHANNEL(self), SPICE_INPUTS_CAP_KEY_SCANCODE); reds_register_channel(reds, RED_CHANNEL(self)); @@ -598,6 +593,8 @@ 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; + channel_class->connect = inputs_connect; + channel_class->migrate = inputs_migrate; } static SpiceKbdInstance* inputs_channel_get_keyboard(InputsChannel *inputs) diff --git a/server/main-channel-client.c b/server/main-channel-client.c index 82b578c8b..4f25462c1 100644 --- a/server/main-channel-client.c +++ b/server/main-channel-client.c @@ -646,14 +646,6 @@ uint64_t main_channel_client_get_roundtrip_ms(MainChannelClient *mcc) return mcc->priv->latency / 1000; } -void main_channel_client_migrate(RedChannelClient *rcc) -{ - RedChannel *channel = red_channel_client_get_channel(rcc); - reds_on_main_channel_migrate(red_channel_get_server(channel), - MAIN_CHANNEL_CLIENT(rcc)); - red_channel_client_default_migrate(rcc); -} - gboolean main_channel_client_connect_semi_seamless(MainChannelClient *mcc) { RedChannelClient *rcc = RED_CHANNEL_CLIENT(mcc); diff --git a/server/main-channel-client.h b/server/main-channel-client.h index a2e38c2fb..dbdf0243d 100644 --- a/server/main-channel-client.h +++ b/server/main-channel-client.h @@ -74,7 +74,6 @@ void main_channel_client_push_init(MainChannelClient *mcc, int multi_media_time, int ram_hint); void main_channel_client_push_notify(MainChannelClient *mcc, const char *msg); -void main_channel_client_migrate(RedChannelClient *rcc); gboolean main_channel_client_connect_semi_seamless(MainChannelClient *mcc); void main_channel_client_connect_seamless(MainChannelClient *mcc); void main_channel_client_handle_migrate_connected(MainChannelClient *mcc, diff --git a/server/main-channel.c b/server/main-channel.c index 4834f79b6..ec0c538ac 100644 --- a/server/main-channel.c +++ b/server/main-channel.c @@ -283,19 +283,22 @@ MainChannel* main_channel_new(RedsState *reds) NULL); } +static void main_channel_client_migrate(RedChannel *self, RedChannelClient *rcc) +{ + reds_on_main_channel_migrate(red_channel_get_server(self), + MAIN_CHANNEL_CLIENT(rcc)); + red_channel_client_default_migrate(rcc); +} + 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, NULL); } static void @@ -319,6 +322,8 @@ 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 cbs */ + 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 9ff3474a7..b8e2e886d 100644 --- a/server/red-channel.c +++ b/server/red-channel.c @@ -91,9 +91,6 @@ struct RedChannelPrivate RedChannelCapabilities local_caps; uint32_t migration_flags; - void *data; - - ClientCbs client_cbs; // TODO: when different channel_clients are in different threads // from Channel -> need to protect! pthread_t thread_id; @@ -201,19 +198,19 @@ red_channel_constructed(GObject *object) spice_assert(klass->on_disconnect); spice_assert(klass->handle_migrate_data || !(self->priv->migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER)); + spice_assert(klass->connect || self->priv->type == SPICE_CHANNEL_MAIN); } -static void red_channel_client_default_connect(RedChannel *channel, RedClient *client, - RedsStream *stream, - int migration, - RedChannelCapabilities *caps) +static void red_channel_default_client_disconnect(RedChannel *self G_GNUC_UNUSED, + RedChannelClient *rcc) { - spice_error("not implemented"); + red_channel_client_disconnect(rcc); } -static void red_channel_client_default_disconnect(RedChannelClient *base) +static void red_channel_default_client_migrate(RedChannel *self G_GNUC_UNUSED, + RedChannelClient *rcc) { - red_channel_client_disconnect(base); + red_channel_client_default_migrate(rcc); } static void @@ -229,6 +226,11 @@ red_channel_class_init(RedChannelClass *klass) object_class->finalize = red_channel_finalize; object_class->constructed = red_channel_constructed; + /* client cbs */ + klass->disconnect = red_channel_default_client_disconnect; + klass->migrate = red_channel_default_client_migrate; + /* 'connect' must be implemented by sub-classes */ + spec = g_param_spec_pointer("spice-server", "spice-server", "The spice server associated with this channel", @@ -296,10 +298,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; } @@ -356,22 +354,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, - gpointer cbs_data) -{ - 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; - } - channel->priv->data = cbs_data; -} - static void add_capability(uint32_t **caps, int *num_caps, uint32_t cap) { int nbefore, n; @@ -489,7 +471,9 @@ void red_channel_connect(RedChannel *channel, RedClient *client, RedsStream *stream, int migration, RedChannelCapabilities *caps) { - channel->priv->client_cbs.connect(channel, client, stream, migration, caps); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + g_return_if_fail(klass->connect); + klass->connect(channel, client, stream, migration, caps); } void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb) @@ -719,10 +703,14 @@ const RedChannelCapabilities* red_channel_get_local_capabilities(RedChannel *sel void red_channel_migrate_client(RedChannel *channel, RedChannelClient *rcc) { - channel->priv->client_cbs.migrate(rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + g_return_if_fail(klass->migrate); + klass->migrate(channel, rcc); } void red_channel_disconnect_client(RedChannel *channel, RedChannelClient *rcc) { - channel->priv->client_cbs.disconnect(rcc); + RedChannelClass *klass = RED_CHANNEL_GET_CLASS(channel); + g_return_if_fail(klass->disconnect); + klass->disconnect(channel, rcc); } diff --git a/server/red-channel.h b/server/red-channel.h index e65eea1eb..c7817fa5e 100644 --- a/server/red-channel.h +++ b/server/red-channel.h @@ -56,22 +56,12 @@ typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient uint32_t size, void *message); -typedef void (*channel_client_connect_proc)(RedChannel *channel, RedClient *client, RedsStream *stream, +typedef void (*channel_client_connect_proc)(RedChannel *self, RedClient *client, RedsStream *stream, int migration, RedChannelCapabilities *caps); -typedef void (*channel_client_disconnect_proc)(RedChannelClient *base); -typedef void (*channel_client_migrate_proc)(RedChannelClient *base); +typedef void (*channel_client_disconnect_proc)(RedChannel *self, RedChannelClient *base); +typedef void (*channel_client_migrate_proc)(RedChannel *self, 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); @@ -120,6 +110,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) \ @@ -135,7 +133,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, gpointer cbs_data); // 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/smartcard.c b/server/smartcard.c index ac2fc1e19..e420c8d1f 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -554,13 +554,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, NULL); - reds_register_channel(reds, RED_CHANNEL(self)); } @@ -579,6 +575,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 cbs */ + channel_class->connect = smartcard_connect_client; } static void smartcard_init(RedsState *reds) diff --git a/server/sound.c b/server/sound.c index 54b897139..4810ac2f5 100644 --- a/server/sound.c +++ b/server/sound.c @@ -1117,7 +1117,8 @@ static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, Re TYPE_PLAYBACK_CHANNEL_CLIENT); } -static void snd_migrate_channel_client(RedChannelClient *rcc) +static void snd_migrate_channel_client(RedChannel *channel G_GNUC_UNUSED, + RedChannelClient *rcc) { snd_set_command(SND_CHANNEL_CLIENT(rcc), SND_MIGRATE_MASK); snd_send(SND_CHANNEL_CLIENT(rcc)); @@ -1331,16 +1332,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, self); - 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); } @@ -1361,6 +1357,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 cbs */ + channel_class->connect = snd_set_playback_peer; + channel_class->migrate = snd_migrate_channel_client; } void snd_attach_playback(RedsState *reds, SpicePlaybackInstance *sin) @@ -1381,16 +1381,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, self); - 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); } @@ -1411,6 +1406,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 cbs */ + 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 9305c9b4b..2f1a5b533 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -225,14 +225,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, NULL); - 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); @@ -767,6 +763,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 cbs */ + channel_class->connect = spicevmc_connect; } static void -- 2.13.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel