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@xxxxxxxxxx> > --- > 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@xxxxxxxxxx> _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel