Blame SOURCES/0005-Notify-client-of-the-creation-of-new-channels-dynami.patch

7bbc9c
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
7bbc9c
From: Frediano Ziglio <fziglio@redhat.com>
7bbc9c
Date: Thu, 24 Aug 2017 23:37:25 +0100
7bbc9c
Subject: [spice-server] Notify client of the creation of new channels
7bbc9c
 dynamically
7bbc9c
7bbc9c
This allows the server to add channels after the client is connected.
7bbc9c
7bbc9c
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
7bbc9c
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
7bbc9c
---
7bbc9c
 server/main-channel-client.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
7bbc9c
 server/main-channel-client.h |  3 +++
7bbc9c
 server/main-channel.c        |  6 ++++++
7bbc9c
 server/main-channel.h        |  3 +++
7bbc9c
 server/reds.c                |  2 ++
7bbc9c
 5 files changed, 65 insertions(+)
7bbc9c
7bbc9c
diff --git a/server/main-channel-client.c b/server/main-channel-client.c
7bbc9c
index b7b60eddb..61a2830fa 100644
7bbc9c
--- a/server/main-channel-client.c
7bbc9c
+++ b/server/main-channel-client.c
7bbc9c
@@ -62,6 +62,7 @@ struct MainChannelClientPrivate {
7bbc9c
     int mig_wait_prev_try_seamless;
7bbc9c
     int init_sent;
7bbc9c
     int seamless_mig_dst;
7bbc9c
+    bool initial_channels_list_sent;
7bbc9c
     uint8_t recv_buf[MAIN_CHANNEL_RECEIVE_BUF_SIZE];
7bbc9c
 };
7bbc9c
 
7bbc9c
@@ -119,6 +120,12 @@ typedef struct RedMultiMediaTimePipeItem {
7bbc9c
     uint32_t time;
7bbc9c
 } RedMultiMediaTimePipeItem;
7bbc9c
 
7bbc9c
+typedef struct RedRegisteredChannelPipeItem {
7bbc9c
+    RedPipeItem base;
7bbc9c
+    uint32_t channel_type;
7bbc9c
+    uint32_t channel_id;
7bbc9c
+} RedRegisteredChannelPipeItem;
7bbc9c
+
7bbc9c
 #define ZERO_BUF_SIZE 4096
7bbc9c
 
7bbc9c
 static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
7bbc9c
@@ -446,6 +453,20 @@ RedPipeItem *main_multi_media_time_item_new(uint32_t mm_time)
7bbc9c
     return &item->base;
7bbc9c
 }
7bbc9c
 
7bbc9c
+RedPipeItem *registered_channel_item_new(RedChannel *channel)
7bbc9c
+{
7bbc9c
+    RedRegisteredChannelPipeItem *item;
7bbc9c
+
7bbc9c
+    item = g_new0(RedRegisteredChannelPipeItem, 1);
7bbc9c
+    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL);
7bbc9c
+
7bbc9c
+    uint32_t type, id;
7bbc9c
+    g_object_get(channel, "channel-type", &type, "id", &id, NULL);
7bbc9c
+    item->channel_type = type;
7bbc9c
+    item->channel_id = id;
7bbc9c
+    return &item->base;
7bbc9c
+}
7bbc9c
+
7bbc9c
 void main_channel_client_handle_migrate_connected(MainChannelClient *mcc,
7bbc9c
                                                   int success,
7bbc9c
                                                   int seamless)
7bbc9c
@@ -927,6 +948,25 @@ static void main_channel_marshall_agent_connected(SpiceMarshaller *m,
7bbc9c
     spice_marshall_msg_main_agent_connected_tokens(m, &connected);
7bbc9c
 }
7bbc9c
 
7bbc9c
+static void main_channel_marshall_registered_channel(RedChannelClient *rcc,
7bbc9c
+                                                     SpiceMarshaller *m,
7bbc9c
+                                                     RedRegisteredChannelPipeItem *item)
7bbc9c
+{
7bbc9c
+    struct {
7bbc9c
+        SpiceMsgChannels info;
7bbc9c
+        SpiceChannelId ids[1];
7bbc9c
+    } channels_info_buffer;
7bbc9c
+    SpiceMsgChannels* channels_info = &channels_info_buffer.info;
7bbc9c
+
7bbc9c
+    red_channel_client_init_send_data(rcc, SPICE_MSG_MAIN_CHANNELS_LIST);
7bbc9c
+
7bbc9c
+    channels_info->channels[0].type = item->channel_type;
7bbc9c
+    channels_info->channels[0].id = item->channel_id;
7bbc9c
+    channels_info->num_of_channels = 1;
7bbc9c
+
7bbc9c
+    spice_marshall_msg_main_channels_list(m, channels_info);
7bbc9c
+}
7bbc9c
+
7bbc9c
 void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
7bbc9c
 {
7bbc9c
     MainChannelClient *mcc = MAIN_CHANNEL_CLIENT(rcc);
7bbc9c
@@ -947,6 +987,7 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
7bbc9c
     switch (base->type) {
7bbc9c
         case RED_PIPE_ITEM_TYPE_MAIN_CHANNELS_LIST:
7bbc9c
             main_channel_marshall_channels(rcc, m, base);
7bbc9c
+            mcc->priv->initial_channels_list_sent = true;
7bbc9c
             break;
7bbc9c
         case RED_PIPE_ITEM_TYPE_MAIN_PING:
7bbc9c
             main_channel_marshall_ping(rcc, m,
7bbc9c
@@ -1003,6 +1044,16 @@ void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
7bbc9c
         case RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS:
7bbc9c
             main_channel_marshall_agent_connected(m, rcc, base);
7bbc9c
             break;
7bbc9c
+        case RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL:
7bbc9c
+            /* The spice protocol requires that the server receive a ATTACH_CHANNELS
7bbc9c
+             * message from the client before sending any CHANNEL_LIST message. If
7bbc9c
+             * we've already sent our initial CHANNELS_LIST message, then it should be
7bbc9c
+             * safe to send new ones for newly-registered channels. */
7bbc9c
+            if (mcc->priv->initial_channels_list_sent) {
7bbc9c
+                main_channel_marshall_registered_channel(rcc, m,
7bbc9c
+                    SPICE_UPCAST(RedRegisteredChannelPipeItem, base));
7bbc9c
+            }
7bbc9c
+            break;
7bbc9c
         default:
7bbc9c
             break;
7bbc9c
     };
7bbc9c
diff --git a/server/main-channel-client.h b/server/main-channel-client.h
7bbc9c
index 26b7e20b8..2cf2e3424 100644
7bbc9c
--- a/server/main-channel-client.h
7bbc9c
+++ b/server/main-channel-client.h
7bbc9c
@@ -122,12 +122,15 @@ enum {
7bbc9c
     RED_PIPE_ITEM_TYPE_MAIN_NAME,
7bbc9c
     RED_PIPE_ITEM_TYPE_MAIN_UUID,
7bbc9c
     RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS,
7bbc9c
+    RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL,
7bbc9c
 };
7bbc9c
 
7bbc9c
 RedPipeItem *main_mouse_mode_item_new(SpiceMouseMode current_mode, int is_client_mouse_allowed);
7bbc9c
 
7bbc9c
 RedPipeItem *main_multi_media_time_item_new(uint32_t mm_time);
7bbc9c
 
7bbc9c
+RedPipeItem *registered_channel_item_new(RedChannel *channel);
7bbc9c
+
7bbc9c
 G_END_DECLS
7bbc9c
 
7bbc9c
 #endif /* MAIN_CHANNEL_CLIENT_H_ */
7bbc9c
diff --git a/server/main-channel.c b/server/main-channel.c
7bbc9c
index eca857f6b..4dc130e40 100644
7bbc9c
--- a/server/main-channel.c
7bbc9c
+++ b/server/main-channel.c
7bbc9c
@@ -149,6 +149,12 @@ static void main_channel_fill_mig_target(MainChannel *main_channel, RedsMigSpice
7bbc9c
     main_channel->mig_target.sport = mig_target->sport;
7bbc9c
 }
7bbc9c
 
7bbc9c
+void
7bbc9c
+main_channel_registered_new_channel(MainChannel *main_chan, RedChannel *channel)
7bbc9c
+{
7bbc9c
+    red_channel_pipes_add(RED_CHANNEL(main_chan), registered_channel_item_new(channel));
7bbc9c
+}
7bbc9c
+
7bbc9c
 void main_channel_migrate_switch(MainChannel *main_chan, RedsMigSpice *mig_target)
7bbc9c
 {
7bbc9c
     main_channel_fill_mig_target(main_chan, mig_target);
7bbc9c
diff --git a/server/main-channel.h b/server/main-channel.h
7bbc9c
index eb3bcec3a..0cb5be728 100644
7bbc9c
--- a/server/main-channel.h
7bbc9c
+++ b/server/main-channel.h
7bbc9c
@@ -66,6 +66,9 @@ void main_channel_push_mouse_mode(MainChannel *main_chan, SpiceMouseMode current
7bbc9c
 void main_channel_push_agent_connected(MainChannel *main_chan);
7bbc9c
 void main_channel_push_agent_disconnected(MainChannel *main_chan);
7bbc9c
 void main_channel_push_multi_media_time(MainChannel *main_chan, uint32_t time);
7bbc9c
+/* tell MainChannel we have a new channel ready */
7bbc9c
+void main_channel_registered_new_channel(MainChannel *main_chan,
7bbc9c
+                                         RedChannel *channel);
7bbc9c
 
7bbc9c
 int main_channel_is_connected(MainChannel *main_chan);
7bbc9c
 
7bbc9c
diff --git a/server/reds.c b/server/reds.c
7bbc9c
index 1b1ab94ea..99b1fd76b 100644
7bbc9c
--- a/server/reds.c
7bbc9c
+++ b/server/reds.c
7bbc9c
@@ -387,6 +387,8 @@ void reds_register_channel(RedsState *reds, RedChannel *channel)
7bbc9c
 {
7bbc9c
     spice_assert(reds);
7bbc9c
     reds->channels = g_list_prepend(reds->channels, channel);
7bbc9c
+    // create new channel in the client if possible
7bbc9c
+    main_channel_registered_new_channel(reds->main_channel, channel);
7bbc9c
 }
7bbc9c
 
7bbc9c
 void reds_unregister_channel(RedsState *reds, RedChannel *channel)