[Spice-devel] [RFC PATCH spice-server v5 02/22] Notify client of the creation of new channels dynamically
Frediano Ziglio
fziglio at redhat.com
Mon Sep 4 11:26:56 UTC 2017
>
> On Wed, 2017-08-30 at 16:28 +0100, Frediano Ziglio wrote:
> > This allows the server to add channels after the client is connected.
> >
> > Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> > ---
> > Changes since v4:
> > - get type and id from channel as soon as possible to
> > prevent possible thread issues;
> > - allocate channels_info on the stack;
> > - do not sent additional channels if channel list was
> > never requested.
> > ---
> > server/main-channel-client.c | 48
> > ++++++++++++++++++++++++++++++++++++++++++++
> > server/main-channel-client.h | 3 +++
> > server/main-channel.c | 6 ++++++
> > server/main-channel.h | 3 +++
> > server/reds.c | 2 ++
> > 5 files changed, 62 insertions(+)
> >
> > diff --git a/server/main-channel-client.c b/server/main-channel-
> > client.c
> > index db8e4823..7268e861 100644
> > --- a/server/main-channel-client.c
> > +++ b/server/main-channel-client.c
> > @@ -62,6 +62,7 @@ struct MainChannelClientPrivate {
> > int mig_wait_prev_try_seamless;
> > int init_sent;
> > int seamless_mig_dst;
> > + bool channels_list_sent;
> > uint8_t recv_buf[MAIN_CHANNEL_RECEIVE_BUF_SIZE];
> > };
> >
> > @@ -119,6 +120,12 @@ typedef struct RedMultiMediaTimePipeItem {
> > uint32_t time;
> > } RedMultiMediaTimePipeItem;
> >
> > +typedef struct RedRegisterChannelPipeItem {
> > + RedPipeItem base;
> > + uint32_t channel_type;
> > + uint32_t channel_id;
> > +} RedRegisterChannelPipeItem;
> > +
> > #define ZERO_BUF_SIZE 4096
> >
> > static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
> > @@ -437,6 +444,21 @@ RedPipeItem
> > *main_multi_media_time_item_new(RedChannelClient *rcc,
> > return &item->base;
> > }
> >
> > +RedPipeItem *register_channel_item_new(RedChannelClient *rcc, void
> > *data, int num)
> > +{
> > + RedChannel *channel = data;
> > + RedRegisterChannelPipeItem *item;
> > +
> > + item = spice_new0(RedRegisterChannelPipeItem, 1);
> > + red_pipe_item_init(&item->base,
> > RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL);
> > +
> > + uint32_t type, id;
> > + g_object_get(channel, "channel-type", &type, "id", &id, NULL);
> > + item->channel_type = type;
> > + item->channel_id = id;
> > + return &item->base;
> > +}
> > +
> > void main_channel_client_handle_migrate_connected(MainChannelClient
> > *mcc,
> > int success,
> > int seamless)
> > @@ -918,6 +940,25 @@ static void
> > main_channel_marshall_agent_connected(SpiceMarshaller *m,
> > spice_marshall_msg_main_agent_connected_tokens(m, &connected);
> > }
> >
> > +static void
> > main_channel_marshall_registered_channel(RedChannelClient *rcc,
> > + SpiceMarshaller
> > *m,
> > + RedRegisterChan
> > nelPipeItem *item)
> > +{
> > + struct {
> > + SpiceMsgChannels info;
> > + SpiceChannelId ids[1];
> > + } channels_info_buffer;
> > + SpiceMsgChannels* channels_info = &channels_info_buffer.info;
> > +
> > + red_channel_client_init_send_data(rcc,
> > SPICE_MSG_MAIN_CHANNELS_LIST);
> > +
> > + channels_info->channels[0].type = item->channel_type;
> > + channels_info->channels[0].id = item->channel_id;
> > + channels_info->num_of_channels = 1;
> > +
> > + spice_marshall_msg_main_channels_list(m, channels_info);
> > +}
> > +
> > void main_channel_client_send_item(RedChannelClient *rcc,
> > RedPipeItem *base)
> > {
> > MainChannelClient *mcc = MAIN_CHANNEL_CLIENT(rcc);
> > @@ -938,6 +979,7 @@ void
> > main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem
> > *base)
> > switch (base->type) {
> > case RED_PIPE_ITEM_TYPE_MAIN_CHANNELS_LIST:
> > main_channel_marshall_channels(rcc, m, base);
> > + mcc->priv->channels_list_sent = true;
> > break;
> > case RED_PIPE_ITEM_TYPE_MAIN_PING:
> > main_channel_marshall_ping(rcc, m,
> > @@ -994,6 +1036,12 @@ void
> > main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem
> > *base)
> > case RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS:
> > main_channel_marshall_agent_connected(m, rcc, base);
> > break;
> > + case RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL:
> > + if (mcc->priv->channels_list_sent) {
> > + main_channel_marshall_registered_channel(rcc, m,
> > + SPICE_UPCAST(RedRegisterChannelPipeItem, base));
> > + }
> > + break;
>
> In a year, I'm sure I won't remember the significance of this
> 'channels_list_sent' variable. I think we should add a comment here.
Mumble... I doubt that if we don't understand now we'll remember in a
year or so. Maybe should be "attach_channels_handled" ?
Or "initial_channels_list_sent" ?
> Something like:
>
> "The spice protocol requires that the server receive a ATTACH_CHANNELS
> message from the client before sending any CHANNEL_LIST message. If
> we've already sent our initial CHANNELS_LIST message, then it should be
> safe to send new ones for newly-registered channels."
>
Added, thanks
>
> > default:
> > break;
> > };
> > diff --git a/server/main-channel-client.h b/server/main-channel-
> > client.h
> > index 0f8e4f49..e936686b 100644
> > --- a/server/main-channel-client.h
> > +++ b/server/main-channel-client.h
> > @@ -122,6 +122,7 @@ enum {
> > RED_PIPE_ITEM_TYPE_MAIN_NAME,
> > RED_PIPE_ITEM_TYPE_MAIN_UUID,
> > RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS,
> > + RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL,
> > };
> >
> > typedef struct MainMouseModeItemInfo {
> > @@ -138,6 +139,8 @@ typedef struct MainMultiMediaTimeItemInfo {
> > RedPipeItem *main_multi_media_time_item_new(RedChannelClient *rcc,
> > void *data, int num);
> >
> > +RedPipeItem *register_channel_item_new(RedChannelClient *rcc, void
> > *data, int num);
> > +
> > G_END_DECLS
> >
> > #endif /* MAIN_CHANNEL_CLIENT_H_ */
> > diff --git a/server/main-channel.c b/server/main-channel.c
> > index 982b6203..ecaab811 100644
> > --- a/server/main-channel.c
> > +++ b/server/main-channel.c
> > @@ -170,6 +170,12 @@ static void
> > main_channel_fill_mig_target(MainChannel *main_channel, RedsMigSpice
> > main_channel->mig_target.sport = mig_target->sport;
> > }
> >
> > +void
> > +main_channel_registered_new_channel(MainChannel *main_chan,
> > RedChannel *channel)
> > +{
> > + red_channel_pipes_new_add(RED_CHANNEL(main_chan),
> > register_channel_item_new, channel);
> > +}
> > +
> > void main_channel_migrate_switch(MainChannel *main_chan,
> > RedsMigSpice *mig_target)
> > {
> > main_channel_fill_mig_target(main_chan, mig_target);
> > diff --git a/server/main-channel.h b/server/main-channel.h
> > index eb3bcec3..0cb5be72 100644
> > --- a/server/main-channel.h
> > +++ b/server/main-channel.h
> > @@ -66,6 +66,9 @@ void main_channel_push_mouse_mode(MainChannel
> > *main_chan, SpiceMouseMode current
> > void main_channel_push_agent_connected(MainChannel *main_chan);
> > void main_channel_push_agent_disconnected(MainChannel *main_chan);
> > void main_channel_push_multi_media_time(MainChannel *main_chan,
> > uint32_t time);
> > +/* tell MainChannel we have a new channel ready */
> > +void main_channel_registered_new_channel(MainChannel *main_chan,
> > + RedChannel *channel);
> >
> > int main_channel_is_connected(MainChannel *main_chan);
> >
> > diff --git a/server/reds.c b/server/reds.c
> > index b6ecc6c6..877d3ba2 100644
> > --- a/server/reds.c
> > +++ b/server/reds.c
> > @@ -387,6 +387,8 @@ void reds_register_channel(RedsState *reds,
> > RedChannel *channel)
> > {
> > spice_assert(reds);
> > reds->channels = g_list_prepend(reds->channels, channel);
> > + // create new channel in the client if possible
> > + main_channel_registered_new_channel(reds->main_channel,
> > channel);
> > }
> >
> > void reds_unregister_channel(RedsState *reds, RedChannel *channel)
>
>
> Aside from comment above, I think it's fine
>
> Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
>
>
Frediano
More information about the Spice-devel
mailing list