[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