> On 30 Aug 2017, at 00:28, Jonathon Jongsma <jjongsma@xxxxxxxxxx> wrote: > > 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; Should we rename “set_xyz_peer” to “xyz_connect”/ > } > > 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;\ These functions are name > } > > 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel