[Spice-devel] [RFC PATCH spice-server v5 02/22] Notify client of the creation of new channels dynamically

Jonathon Jongsma jjongsma at redhat.com
Fri Sep 1 19:22:28 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.
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."


>          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>



More information about the Spice-devel mailing list