diff --git a/.gitignore b/.gitignore
index 657c9f5..2e95719 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/spice-0.12.8.tar.bz2
+SOURCES/spice-0.14.0.tar.bz2
diff --git a/.spice.metadata b/.spice.metadata
index fc820d6..f0a186a 100644
--- a/.spice.metadata
+++ b/.spice.metadata
@@ -1 +1 @@
-5f19057c5c17c1b6d601c386e6404b44ec77461f SOURCES/spice-0.12.8.tar.bz2
+93e42588d1aac0a3c127ada1e5d8f40be84776a9 SOURCES/spice-0.14.0.tar.bz2
diff --git a/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch b/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch
deleted file mode 100644
index f9470ab..0000000
--- a/SOURCES/0001-Call-migrate_end_complete-after-falling-back-to-swit.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
-Date: Wed, 20 Jul 2016 17:16:31 +0400
-Subject: [PATCH] Call migrate_end_complete() after falling back to switch-host
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Eventually, during a seamless migration, qemu may finish to migrate
-before the spice client even finished to connect all channels to
-destination and informed the server. In this case,
-main_channel_client_migrate_src_complete() will fall back to
-switch-host method, and reds_mig_fill_wait_disconnect() is called to
-complete the migration (disconnecting all channels).
-
-reds_mig_cleanup() is called when all channels are disconnected, but
-reds->mig_wait_connect is still TRUE, and it will call
-migrate_connect_complete() instead of the expected
-migrate_end_complete(). Setting reds->mig_wait_connect to FALSE when
-reds_mig_fill_wait_disconnect() solves the issue.
-
-Fixes:
-https://bugzilla.redhat.com/show_bug.cgi?id=1352836
-
-Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
----
- server/reds.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/server/reds.c b/server/reds.c
-index 61bf735..f40b65c 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -2816,6 +2816,7 @@ static void reds_mig_fill_wait_disconnect(void)
-         wait_client->client = client;
-         ring_add(&reds->mig_wait_disconnect_clients, &wait_client->link);
-     }
-+    reds->mig_wait_connect = FALSE;
-     reds->mig_wait_disconnect = TRUE;
-     core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
- }
diff --git a/SOURCES/0001-inputs-channel-Check-message-size-handling-migration.patch b/SOURCES/0001-inputs-channel-Check-message-size-handling-migration.patch
new file mode 100644
index 0000000..3438403
--- /dev/null
+++ b/SOURCES/0001-inputs-channel-Check-message-size-handling-migration.patch
@@ -0,0 +1,32 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Fri, 6 Oct 2017 09:38:31 +0100
+Subject: [spice-server] inputs-channel: Check message size handling migration
+ data
+
+Prevent possible buffer reading overflow.
+Note that message pointer must be valid and data are checked
+value by value so even on overflow you just get an error.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/inputs-channel.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/server/inputs-channel.c b/server/inputs-channel.c
+index 8e17cc724..11a338a26 100644
+--- a/server/inputs-channel.c
++++ b/server/inputs-channel.c
+@@ -505,6 +505,11 @@ static bool inputs_channel_handle_migrate_data(RedChannelClient *rcc,
+     SpiceMigrateDataHeader *header;
+     SpiceMigrateDataInputs *mig_data;
+ 
++    if (size < sizeof(SpiceMigrateDataHeader) + sizeof(SpiceMigrateDataInputs)) {
++        spice_warning("bad message size %u", size);
++        return FALSE;
++    }
++
+     header = (SpiceMigrateDataHeader *)message;
+     mig_data = (SpiceMigrateDataInputs *)(header + 1);
+ 
diff --git a/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch b/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch
deleted file mode 100644
index 70339b3..0000000
--- a/SOURCES/0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Mon, 28 Nov 2016 13:15:58 +0000
-Subject: [PATCH] Prevent possible DoS attempts during protocol handshake
-
-The limit for link message is specified using a 32 bit unsigned integer.
-This could cause possible DoS due to excessive memory allocations and
-some possible crashes.
-For instance a value >= 2^31 causes a spice_assert to be triggered in
-async_read_handler (reds-stream.c) due to an integer overflow at this
-line:
-
-   int n = async->end - async->now;
-
-This could be easily triggered with a program like
-
-  #!/usr/bin/env python
-
-  import socket
-  import time
-  from struct import pack
-
-  server = '127.0.0.1'
-  port = 5900
-
-  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-  s.connect((server, port))
-  data = pack('<4sIII', 'REDQ', 2, 2, 0xaaaaaaaa)
-  s.send(data)
-
-  time.sleep(1)
-
-without requiring any authentication (the same can be done
-with TLS).
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/reds.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/server/reds.c b/server/reds.c
-index f40b65c..86a33d5 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -2202,7 +2202,8 @@ static void reds_handle_read_header_done(void *opaque)
- 
-     reds->peer_minor_version = header->minor_version;
- 
--    if (header->size < sizeof(SpiceLinkMess)) {
-+    /* the check for 4096 is to avoid clients to cause arbitrary big memory allocations */
-+    if (header->size < sizeof(SpiceLinkMess) || header->size > 4096) {
-         reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA);
-         spice_warning("bad size %u", header->size);
-         reds_link_free(link);
diff --git a/SOURCES/0002-red-channel-Remove-red_channel_init_outgoing_message.patch b/SOURCES/0002-red-channel-Remove-red_channel_init_outgoing_message.patch
new file mode 100644
index 0000000..1b06a0a
--- /dev/null
+++ b/SOURCES/0002-red-channel-Remove-red_channel_init_outgoing_message.patch
@@ -0,0 +1,66 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Fri, 6 Oct 2017 08:57:42 +0100
+Subject: [spice-server] red-channel: Remove
+ red_channel_init_outgoing_messages_window
+
+This function does not make much sense anymore.
+Is called by RedVmcChannel which doesn't use RedChannelClient ACKs
+so the variable changed are not used.
+Moreover, at red_vmc_channel_constructed() time, there will be no
+clients yet, so red_channel_init_outgoing_messages() will be a no-op.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/red-channel.c | 8 --------
+ server/red-channel.h | 3 ---
+ server/spicevmc.c    | 2 --
+ 3 files changed, 13 deletions(-)
+
+diff --git a/server/red-channel.c b/server/red-channel.c
+index b5094829e..8c507f202 100644
+--- a/server/red-channel.c
++++ b/server/red-channel.c
+@@ -421,14 +421,6 @@ void red_channel_push(RedChannel *channel)
+     g_list_foreach(channel->priv->clients, (GFunc)red_channel_client_push, NULL);
+ }
+ 
+-// TODO: this function doesn't make sense because the window should be client (WAN/LAN)
+-// specific
+-void red_channel_init_outgoing_messages_window(RedChannel *channel)
+-{
+-    g_list_foreach(channel->priv->clients,
+-                   (GFunc)red_channel_client_init_outgoing_messages_window, NULL);
+-}
+-
+ void red_channel_pipes_add(RedChannel *channel, RedPipeItem *item)
+ {
+     RedChannelClient *rcc;
+diff --git a/server/red-channel.h b/server/red-channel.h
+index e0fe94fec..281ed0c9e 100644
+--- a/server/red-channel.h
++++ b/server/red-channel.h
+@@ -157,9 +157,6 @@ void red_channel_destroy(RedChannel *channel);
+ /* return true if all the channel clients support the cap */
+ bool red_channel_test_remote_cap(RedChannel *channel, uint32_t cap);
+ 
+-/* should be called when a new channel is ready to send messages */
+-void red_channel_init_outgoing_messages_window(RedChannel *channel);
+-
+ // helper to push a new item to all channels
+ typedef RedPipeItem *(*new_pipe_item_t)(RedChannelClient *rcc, void *data, int num);
+ int red_channel_pipes_new_add(RedChannel *channel, new_pipe_item_t creator, void *data);
+diff --git a/server/spicevmc.c b/server/spicevmc.c
+index 6b9b96fc8..a1685483d 100644
+--- a/server/spicevmc.c
++++ b/server/spicevmc.c
+@@ -246,8 +246,6 @@ red_vmc_channel_constructed(GObject *object)
+     red_channel_set_cap(RED_CHANNEL(self), SPICE_SPICEVMC_CAP_DATA_COMPRESS_LZ4);
+ #endif
+ 
+-    red_channel_init_outgoing_messages_window(RED_CHANNEL(self));
+-
+     reds_register_channel(reds, RED_CHANNEL(self));
+ }
+ 
diff --git a/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch b/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch
deleted file mode 100644
index 5571a12..0000000
--- a/SOURCES/0003-Prevent-integer-overflows-in-capability-checks.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Mon, 28 Nov 2016 13:15:58 +0000
-Subject: [PATCH] Prevent integer overflows in capability checks
-
-The limits for capabilities are specified using 32 bit unsigned integers.
-This could cause possible integer overflows causing buffer overflows.
-For instance the sum of num_common_caps and num_caps can be 0 avoiding
-additional checks.
-As the link message is now capped to 4096 and the capabilities are
-contained in the link message, this commit limits the capabilities
-to 1024 (capabilities are expressed in number of uint32_t items).
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/reds.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/server/reds.c b/server/reds.c
-index 86a33d5..c639aa3 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -2113,6 +2113,14 @@ static void reds_handle_read_link_done(void *opaque)
-     num_caps = link_mess->num_common_caps + link_mess->num_channel_caps;
-     caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset);
- 
-+    /* Prevent integer overflows. Currently we defined only 13 capabilities,
-+     * I expect 1024 to be valid for quite a lot time */
-+    if (link_mess->num_channel_caps > 1024 || link_mess->num_common_caps > 1024) {
-+        reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA);
-+        reds_link_free(link);
-+        return;
-+    }
-+
-     if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset >
-                      link->link_header.size ||
-                      link_mess->caps_offset < sizeof(*link_mess))) {
diff --git a/SOURCES/0003-reds-Remove-leak-allocating-migration-state.patch b/SOURCES/0003-reds-Remove-leak-allocating-migration-state.patch
new file mode 100644
index 0000000..dc6b99f
--- /dev/null
+++ b/SOURCES/0003-reds-Remove-leak-allocating-migration-state.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 19 Sep 2017 08:28:02 +0100
+Subject: [spice-server] reds: Remove leak allocating migration state
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/reds.c | 2 +-
+ server/reds.h | 4 ----
+ 2 files changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/server/reds.c b/server/reds.c
+index 12c33570a..1b1ab94ea 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -3378,7 +3378,7 @@ SPICE_GNUC_VISIBLE int spice_server_add_interface(SpiceServer *reds,
+             return -1;
+         }
+         reds->migration_interface = SPICE_CONTAINEROF(sin, SpiceMigrateInstance, base);
+-        reds->migration_interface->st = spice_new0(SpiceMigrateState, 1);
++        reds->migration_interface->st = (SpiceMigrateState *)(intptr_t)1; // dummy pointer
+     }
+ 
+     return 0;
+diff --git a/server/reds.h b/server/reds.h
+index 4f5fc28c3..cea002c51 100644
+--- a/server/reds.h
++++ b/server/reds.h
+@@ -35,10 +35,6 @@ static inline QXLInterface * qxl_get_interface(QXLInstance *qxl)
+     return SPICE_CONTAINEROF(qxl->base.sif, QXLInterface, base);
+ }
+ 
+-struct SpiceMigrateState {
+-    int dummy;
+-};
+-
+ /* main thread only */
+ void reds_handle_channel_event(RedsState *reds, int event, SpiceChannelEventInfo *info);
+ 
diff --git a/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch b/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch
deleted file mode 100644
index b5d265a..0000000
--- a/SOURCES/0004-main-channel-Prevent-overflow-reading-messages-from-.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Tue, 29 Nov 2016 16:46:56 +0000
-Subject: [PATCH] main-channel: Prevent overflow reading messages from client
-
-Caller is supposed the function return a buffer able to store
-size bytes.
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/main_channel.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/server/main_channel.c b/server/main_channel.c
-index 0ecc9df..1fc3915 100644
---- a/server/main_channel.c
-+++ b/server/main_channel.c
-@@ -1026,6 +1026,9 @@ static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
- 
-     if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
-         return reds_get_agent_data_buffer(mcc, size);
-+    } else if (size > sizeof(main_chan->recv_buf)) {
-+        /* message too large, caller will log a message and close the connection */
-+        return NULL;
-     } else {
-         return main_chan->recv_buf;
-     }
diff --git a/SOURCES/0004-tests-Check-leaks-registering-migration-interface.patch b/SOURCES/0004-tests-Check-leaks-registering-migration-interface.patch
new file mode 100644
index 0000000..3ba2f44
--- /dev/null
+++ b/SOURCES/0004-tests-Check-leaks-registering-migration-interface.patch
@@ -0,0 +1,64 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 19 Sep 2017 08:27:38 +0100
+Subject: [spice-server] tests: Check leaks registering migration interface
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Christophe Fergeau <cfergeau@redhat.com>
+---
+ server/tests/test-leaks.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/server/tests/test-leaks.c b/server/tests/test-leaks.c
+index 04dcac4f4..7032000aa 100644
+--- a/server/tests/test-leaks.c
++++ b/server/tests/test-leaks.c
+@@ -143,12 +143,48 @@ static void vmc_leaks(void)
+     basic_event_loop_destroy();
+ }
+ 
++static void migrate_cb(SpiceMigrateInstance *sin)
++{
++}
++
++static const SpiceMigrateInterface migrate_interface = {
++    .base = {
++        .type          = SPICE_INTERFACE_MIGRATION,
++        .description   = "migration",
++        .major_version = SPICE_INTERFACE_MIGRATION_MAJOR,
++        .minor_version = SPICE_INTERFACE_MIGRATION_MINOR,
++    },
++    .migrate_connect_complete = migrate_cb,
++    .migrate_end_complete = migrate_cb,
++};
++
++static void migration_leaks(void)
++{
++    SpiceCoreInterface *core;
++    SpiceServer *server = spice_server_new();
++    SpiceMigrateInstance migrate;
++
++    g_assert_nonnull(server);
++
++    core = basic_event_loop_init();
++    g_assert_nonnull(core);
++
++    g_assert_cmpint(spice_server_init(server, core), ==, 0);
++
++    migrate.base.sif = &migrate_interface.base;
++    spice_server_add_interface(server, &migrate.base);
++
++    spice_server_destroy(server);
++    basic_event_loop_destroy();
++}
++
+ int main(int argc, char *argv[])
+ {
+     g_test_init(&argc, &argv, NULL);
+ 
+     g_test_add_func("/server/server leaks", server_leaks);
+     g_test_add_func("/server/vmc leaks", vmc_leaks);
++    g_test_add_func("/server/migration leaks", migration_leaks);
+ 
+     return g_test_run();
+ }
diff --git a/SOURCES/0005-Notify-client-of-the-creation-of-new-channels-dynami.patch b/SOURCES/0005-Notify-client-of-the-creation-of-new-channels-dynami.patch
new file mode 100644
index 0000000..8937a67
--- /dev/null
+++ b/SOURCES/0005-Notify-client-of-the-creation-of-new-channels-dynami.patch
@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Thu, 24 Aug 2017 23:37:25 +0100
+Subject: [spice-server] Notify client of the creation of new channels
+ dynamically
+
+This allows the server to add channels after the client is connected.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/main-channel-client.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
+ server/main-channel-client.h |  3 +++
+ server/main-channel.c        |  6 ++++++
+ server/main-channel.h        |  3 +++
+ server/reds.c                |  2 ++
+ 5 files changed, 65 insertions(+)
+
+diff --git a/server/main-channel-client.c b/server/main-channel-client.c
+index b7b60eddb..61a2830fa 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 initial_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 RedRegisteredChannelPipeItem {
++    RedPipeItem base;
++    uint32_t channel_type;
++    uint32_t channel_id;
++} RedRegisteredChannelPipeItem;
++
+ #define ZERO_BUF_SIZE 4096
+ 
+ static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
+@@ -446,6 +453,20 @@ RedPipeItem *main_multi_media_time_item_new(uint32_t mm_time)
+     return &item->base;
+ }
+ 
++RedPipeItem *registered_channel_item_new(RedChannel *channel)
++{
++    RedRegisteredChannelPipeItem *item;
++
++    item = g_new0(RedRegisteredChannelPipeItem, 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)
+@@ -927,6 +948,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,
++                                                     RedRegisteredChannelPipeItem *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);
+@@ -947,6 +987,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->initial_channels_list_sent = true;
+             break;
+         case RED_PIPE_ITEM_TYPE_MAIN_PING:
+             main_channel_marshall_ping(rcc, m,
+@@ -1003,6 +1044,16 @@ 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:
++            /* 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. */
++            if (mcc->priv->initial_channels_list_sent) {
++                main_channel_marshall_registered_channel(rcc, m,
++                    SPICE_UPCAST(RedRegisteredChannelPipeItem, base));
++            }
++            break;
+         default:
+             break;
+     };
+diff --git a/server/main-channel-client.h b/server/main-channel-client.h
+index 26b7e20b8..2cf2e3424 100644
+--- a/server/main-channel-client.h
++++ b/server/main-channel-client.h
+@@ -122,12 +122,15 @@ 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,
+ };
+ 
+ RedPipeItem *main_mouse_mode_item_new(SpiceMouseMode current_mode, int is_client_mouse_allowed);
+ 
+ RedPipeItem *main_multi_media_time_item_new(uint32_t mm_time);
+ 
++RedPipeItem *registered_channel_item_new(RedChannel *channel);
++
+ G_END_DECLS
+ 
+ #endif /* MAIN_CHANNEL_CLIENT_H_ */
+diff --git a/server/main-channel.c b/server/main-channel.c
+index eca857f6b..4dc130e40 100644
+--- a/server/main-channel.c
++++ b/server/main-channel.c
+@@ -149,6 +149,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_add(RED_CHANNEL(main_chan), registered_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 eb3bcec3a..0cb5be728 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 1b1ab94ea..99b1fd76b 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)
diff --git a/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch b/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch
deleted file mode 100644
index 70e183d..0000000
--- a/SOURCES/0005-reds-Check-link-header-magic-without-waiting-for-the.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Thu, 26 Jan 2017 15:53:18 +0000
-Subject: [PATCH] reds: Check link header magic without waiting for the whole
- header
-
-This allows the connection to early fail in case initial bytes
-are not correct.
-This allows for instance VNC client to graceful fail connecting
-to a spice-server. This happens easily as the two protocols
-share the same range of ports.
-
-This resolves rhbz#1416692.
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-Acked-by: Christophe Fergeau <cfergeau@redhat.com>
----
- server/reds.c | 28 ++++++++++++++++++++--------
- 1 file changed, 20 insertions(+), 8 deletions(-)
-
-diff --git a/server/reds.c b/server/reds.c
-index c639aa3..57a93c9 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -2192,12 +2192,6 @@ static void reds_handle_read_header_done(void *opaque)
-     header->minor_version = GUINT32_FROM_LE(header->minor_version);
-     header->size = GUINT32_FROM_LE(header->size);
- 
--    if (header->magic != SPICE_MAGIC) {
--        reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC);
--        reds_link_free(link);
--        return;
--    }
--
-     if (header->major_version != SPICE_VERSION_MAJOR) {
-         if (header->major_version > 0) {
-             reds_send_link_error(link, SPICE_LINK_ERR_VERSION_MISMATCH);
-@@ -2227,13 +2221,31 @@ static void reds_handle_read_header_done(void *opaque)
-                            link);
- }
- 
-+static void reds_handle_read_magic_done(void *opaque)
-+{
-+    RedLinkInfo *link = (RedLinkInfo *)opaque;
-+    const SpiceLinkHeader *header = &link->link_header;
-+
-+    if (header->magic != SPICE_MAGIC) {
-+        reds_send_link_error(link, SPICE_LINK_ERR_INVALID_MAGIC);
-+        reds_link_free(link);
-+        return;
-+    }
-+
-+    reds_stream_async_read(link->stream,
-+                           ((uint8_t *)&link->link_header) + sizeof(header->magic),
-+                           sizeof(SpiceLinkHeader) - sizeof(header->magic),
-+                           reds_handle_read_header_done,
-+                           link);
-+}
-+
- static void reds_handle_new_link(RedLinkInfo *link)
- {
-     reds_stream_set_async_error_handler(link->stream, reds_handle_link_error);
-     reds_stream_async_read(link->stream,
-                            (uint8_t *)&link->link_header,
--                           sizeof(SpiceLinkHeader),
--                           reds_handle_read_header_done,
-+                           sizeof(link->link_header.magic),
-+                           reds_handle_read_magic_done,
-                            link);
- }
- 
diff --git a/SOURCES/0006-reds-Disconnect-when-receiving-overly-big-ClientMoni.patch b/SOURCES/0006-reds-Disconnect-when-receiving-overly-big-ClientMoni.patch
deleted file mode 100644
index 2db5566..0000000
--- a/SOURCES/0006-reds-Disconnect-when-receiving-overly-big-ClientMoni.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Mon, 15 May 2017 15:57:28 +0100
-Subject: [PATCH] reds: Disconnect when receiving overly big
- ClientMonitorsConfig
-
-Total message size received from the client was unlimited. There is
-a 2kiB size check on individual agent messages, but the MonitorsConfig
-message can be split in multiple chunks, and the size of the
-non-chunked MonitorsConfig message was never checked. This could easily
-lead to memory exhaustion on the host.
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/reds.c | 25 +++++++++++++++++++++++--
- 1 file changed, 23 insertions(+), 2 deletions(-)
-
-diff --git a/server/reds.c b/server/reds.c
-index 57a93c9..95293dd 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -993,19 +993,34 @@ static void reds_client_monitors_config_cleanup(void)
- static void reds_on_main_agent_monitors_config(
-         MainChannelClient *mcc, void *message, size_t size)
- {
-+    const unsigned int MAX_MONITORS = 256;
-+    const unsigned int MAX_MONITOR_CONFIG_SIZE =
-+       sizeof(VDAgentMonitorsConfig) + MAX_MONITORS * sizeof(VDAgentMonConfig);
-+
-     VDAgentMessage *msg_header;
-     VDAgentMonitorsConfig *monitors_config;
-     RedsClientMonitorsConfig *cmc = &reds->client_monitors_config;
- 
-+    // limit size of message sent by the client as this can cause a DoS through
-+    // memory exhaustion, or potentially some integer overflows
-+    if (sizeof(VDAgentMessage) + MAX_MONITOR_CONFIG_SIZE - cmc->buffer_size < size) {
-+        goto overflow;
-+    }
-     cmc->buffer_size += size;
-     cmc->buffer = realloc(cmc->buffer, cmc->buffer_size);
-     spice_assert(cmc->buffer);
-     cmc->mcc = mcc;
-     memcpy(cmc->buffer + cmc->buffer_pos, message, size);
-     cmc->buffer_pos += size;
-+    if (sizeof(VDAgentMessage) > cmc->buffer_size) {
-+        spice_debug("not enough data yet. %d", cmc->buffer_size);
-+        return;
-+    }
-     msg_header = (VDAgentMessage *)cmc->buffer;
--    if (sizeof(VDAgentMessage) > cmc->buffer_size ||
--            msg_header->size > cmc->buffer_size - sizeof(VDAgentMessage)) {
-+    if (msg_header->size > MAX_MONITOR_CONFIG_SIZE) {
-+        goto overflow;
-+    }
-+    if (msg_header->size > cmc->buffer_size - sizeof(VDAgentMessage)) {
-         spice_debug("not enough data yet. %d", cmc->buffer_size);
-         return;
-     }
-@@ -1013,6 +1028,12 @@ static void reds_on_main_agent_monitors_config(
-     spice_debug("%s: %d", __func__, monitors_config->num_of_monitors);
-     red_dispatcher_client_monitors_config(monitors_config);
-     reds_client_monitors_config_cleanup();
-+    return;
-+
-+overflow:
-+    spice_warning("received invalid MonitorsConfig request from client, disconnecting");
-+    red_channel_client_disconnect(main_channel_client_get_base(mcc));
-+    reds_client_monitors_config_cleanup();
- }
- 
- void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size)
diff --git a/SOURCES/0006-stream-device-Add-device-to-handle-streaming.patch b/SOURCES/0006-stream-device-Add-device-to-handle-streaming.patch
new file mode 100644
index 0000000..22cdee7
--- /dev/null
+++ b/SOURCES/0006-stream-device-Add-device-to-handle-streaming.patch
@@ -0,0 +1,194 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 11:24:58 +0000
+Subject: [spice-server] stream-device: Add device to handle streaming
+
+Add a stub device in guest.
+The aim of this device is to make it possible for the guest to send a
+stream through a DisplayChannel (in the sense of protocol channel).
+This stub allows the guest to send some data and you can see some debug
+lines of data arrived on host logs.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/Makefile.am     |   1 +
+ server/char-device.h   |   1 +
+ server/reds.c          |   2 +
+ server/stream-device.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 134 insertions(+)
+ create mode 100644 server/stream-device.c
+
+diff --git a/server/Makefile.am b/server/Makefile.am
+index 5d5590af9..f08ddf883 100644
+--- a/server/Makefile.am
++++ b/server/Makefile.am
+@@ -166,6 +166,7 @@ libserver_la_SOURCES =				\
+ 	stat.h					\
+ 	stream.c				\
+ 	stream.h				\
++	stream-device.c				\
+ 	sw-canvas.c				\
+ 	tree.c					\
+ 	tree.h					\
+diff --git a/server/char-device.h b/server/char-device.h
+index dccd576da..54a1ef939 100644
+--- a/server/char-device.h
++++ b/server/char-device.h
+@@ -236,6 +236,7 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds,
+                                        uint8_t channel_type);
+ void spicevmc_device_disconnect(RedsState *reds,
+                                 SpiceCharDeviceInstance *char_device);
++RedCharDevice *stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin);
+ 
+ SpiceCharDeviceInterface *spice_char_device_get_interface(SpiceCharDeviceInstance *instance);
+ 
+diff --git a/server/reds.c b/server/reds.c
+index 99b1fd76b..b24f61ab2 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -3223,6 +3223,8 @@ static int spice_server_char_device_add_interface(SpiceServer *reds,
+     else if (strcmp(char_device->subtype, SUBTYPE_PORT) == 0) {
+         if (strcmp(char_device->portname, "org.spice-space.webdav.0") == 0) {
+             dev_state = spicevmc_device_connect(reds, char_device, SPICE_CHANNEL_WEBDAV);
++        } else if (strcmp(char_device->portname, "com.redhat.stream.0") == 0) {
++            dev_state = stream_device_connect(reds, char_device);
+         } else {
+             dev_state = spicevmc_device_connect(reds, char_device, SPICE_CHANNEL_PORT);
+         }
+diff --git a/server/stream-device.c b/server/stream-device.c
+new file mode 100644
+index 000000000..f3a147b80
+--- /dev/null
++++ b/server/stream-device.c
+@@ -0,0 +1,130 @@
++/* spice-server character device to handle a video stream
++
++   Copyright (C) 2017 Red Hat, Inc.
++
++   This library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   This library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with this library; if not, see <http://www.gnu.org/licenses/>.
++*/
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include "char-device.h"
++
++#define TYPE_STREAM_DEVICE stream_device_get_type()
++
++#define STREAM_DEVICE(obj) \
++    (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_STREAM_DEVICE, StreamDevice))
++#define STREAM_DEVICE_CLASS(klass) \
++    (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_STREAM_DEVICE, StreamDeviceClass))
++#define STREAM_DEVICE_GET_CLASS(obj) \
++    (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_DEVICE, StreamDeviceClass))
++
++typedef struct StreamDevice StreamDevice;
++typedef struct StreamDeviceClass StreamDeviceClass;
++
++struct StreamDevice {
++    RedCharDevice parent;
++};
++
++struct StreamDeviceClass {
++    RedCharDeviceClass parent_class;
++};
++
++static GType stream_device_get_type(void) G_GNUC_CONST;
++static StreamDevice *stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds);
++
++G_DEFINE_TYPE(StreamDevice, stream_device, RED_TYPE_CHAR_DEVICE)
++
++static RedPipeItem *
++stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *sin)
++{
++    SpiceCharDeviceInterface *sif;
++    int n;
++
++    sif = spice_char_device_get_interface(sin);
++
++    do {
++        uint8_t buf[256];
++        n = sif->read(sin, buf, sizeof(buf));
++        spice_debug("read %d bytes from device", n);
++    } while (n > 0);
++
++    return NULL;
++}
++
++static void
++stream_device_send_msg_to_client(RedCharDevice *self, RedPipeItem *msg, RedClient *client)
++{
++}
++
++static void
++stream_device_send_tokens_to_client(RedCharDevice *self, RedClient *client, uint32_t tokens)
++{
++    spice_printerr("Not implemented!");
++}
++
++static void
++stream_device_remove_client(RedCharDevice *self, RedClient *client)
++{
++}
++
++RedCharDevice *
++stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
++{
++    SpiceCharDeviceInterface *sif;
++
++    StreamDevice *dev = stream_device_new(sin, reds);
++
++    sif = spice_char_device_get_interface(sin);
++    if (sif->state) {
++        sif->state(sin, 1);
++    }
++
++    return RED_CHAR_DEVICE(dev);
++}
++
++static void
++stream_device_dispose(GObject *object)
++{
++}
++
++static void
++stream_device_class_init(StreamDeviceClass *klass)
++{
++    GObjectClass *object_class = G_OBJECT_CLASS(klass);
++    RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
++
++    object_class->dispose = stream_device_dispose;
++
++    char_dev_class->read_one_msg_from_device = stream_device_read_msg_from_dev;
++    char_dev_class->send_msg_to_client = stream_device_send_msg_to_client;
++    char_dev_class->send_tokens_to_client = stream_device_send_tokens_to_client;
++    char_dev_class->remove_client = stream_device_remove_client;
++}
++
++static void
++stream_device_init(StreamDevice *self)
++{
++}
++
++static StreamDevice *
++stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
++{
++    return g_object_new(TYPE_STREAM_DEVICE,
++                        "sin", sin,
++                        "spice-server", reds,
++                        "client-tokens-interval", 0ULL,
++                        "self-tokens", ~0ULL,
++                        NULL);
++}
diff --git a/SOURCES/0007-reds-Avoid-integer-overflows-handling-monitor-config.patch b/SOURCES/0007-reds-Avoid-integer-overflows-handling-monitor-config.patch
deleted file mode 100644
index 2ea6f24..0000000
--- a/SOURCES/0007-reds-Avoid-integer-overflows-handling-monitor-config.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Mon, 15 May 2017 15:57:28 +0100
-Subject: [PATCH] reds: Avoid integer overflows handling monitor configuration
-
-Avoid VDAgentMessage::size integer overflows.
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/reds.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/server/reds.c b/server/reds.c
-index 95293dd..eda3486 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -1024,6 +1024,9 @@ static void reds_on_main_agent_monitors_config(
-         spice_debug("not enough data yet. %d", cmc->buffer_size);
-         return;
-     }
-+    if (msg_header->size < sizeof(VDAgentMonitorsConfig)) {
-+        goto overflow;
-+    }
-     monitors_config = (VDAgentMonitorsConfig *)(cmc->buffer + sizeof(*msg_header));
-     spice_debug("%s: %d", __func__, monitors_config->num_of_monitors);
-     red_dispatcher_client_monitors_config(monitors_config);
diff --git a/SOURCES/0007-stream-device-Start-parsing-new-protocol-from-guest.patch b/SOURCES/0007-stream-device-Start-parsing-new-protocol-from-guest.patch
new file mode 100644
index 0000000..872697a
--- /dev/null
+++ b/SOURCES/0007-stream-device-Start-parsing-new-protocol-from-guest.patch
@@ -0,0 +1,178 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Fri, 13 Jan 2017 18:20:43 +0000
+Subject: [spice-server] stream-device: Start parsing new protocol from guest
+
+Parse the data sent from the guest to the streaming device.
+At the moment, the data is simply discarded after it is parsed.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-device.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 124 insertions(+), 4 deletions(-)
+
+diff --git a/server/stream-device.c b/server/stream-device.c
+index f3a147b80..58edb3d11 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -19,6 +19,8 @@
+ #include <config.h>
+ #endif
+ 
++#include <spice/stream-device.h>
++
+ #include "char-device.h"
+ 
+ #define TYPE_STREAM_DEVICE stream_device_get_type()
+@@ -35,6 +37,9 @@ typedef struct StreamDeviceClass StreamDeviceClass;
+ 
+ struct StreamDevice {
+     RedCharDevice parent;
++    StreamDevHeader hdr;
++    uint8_t hdr_pos;
++    bool has_error;
+ };
+ 
+ struct StreamDeviceClass {
+@@ -46,21 +51,136 @@ static StreamDevice *stream_device_new(SpiceCharDeviceInstance *sin, RedsState *
+ 
+ G_DEFINE_TYPE(StreamDevice, stream_device, RED_TYPE_CHAR_DEVICE)
+ 
++typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin)
++    SPICE_GNUC_WARN_UNUSED_RESULT;
++
++static StreamMsgHandler handle_msg_format, handle_msg_data;
++
++static bool handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin,
++                               const char *error_msg) SPICE_GNUC_WARN_UNUSED_RESULT;
++
+ static RedPipeItem *
+ stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *sin)
+ {
++    StreamDevice *dev = STREAM_DEVICE(self);
+     SpiceCharDeviceInterface *sif;
+     int n;
++    bool handled = false;
++
++    if (dev->has_error) {
++        return NULL;
++    }
+ 
+     sif = spice_char_device_get_interface(sin);
+ 
+-    do {
+-        uint8_t buf[256];
++    /* read header */
++    while (dev->hdr_pos < sizeof(dev->hdr)) {
++        n = sif->read(sin, (uint8_t *) &dev->hdr, sizeof(dev->hdr) - dev->hdr_pos);
++        if (n <= 0) {
++            return NULL;
++        }
++        dev->hdr_pos += n;
++        if (dev->hdr_pos >= sizeof(dev->hdr)) {
++            dev->hdr.type = GUINT16_FROM_LE(dev->hdr.type);
++            dev->hdr.size = GUINT32_FROM_LE(dev->hdr.size);
++        }
++    }
++
++    switch ((StreamMsgType) dev->hdr.type) {
++    case STREAM_TYPE_FORMAT:
++        if (dev->hdr.size != sizeof(StreamMsgFormat)) {
++            handled = handle_msg_invalid(dev, sin, "Wrong size for StreamMsgFormat");
++        } else {
++            handled = handle_msg_format(dev, sin);
++        }
++        break;
++    case STREAM_TYPE_DATA:
++        handled = handle_msg_data(dev, sin);
++        break;
++    case STREAM_TYPE_CAPABILITIES:
++        /* FIXME */
++    default:
++        handled = handle_msg_invalid(dev, sin, "Invalid message type");
++        break;
++    }
++
++    /* current message has been handled, so reset state and get ready to parse
++     * the next message */
++    if (handled) {
++        dev->hdr_pos = 0;
++    }
++
++    return NULL;
++}
++
++static bool
++handle_msg_invalid(StreamDevice *dev, SpiceCharDeviceInstance *sin, const char *error_msg)
++{
++    static const char default_error_msg[] = "Protocol error";
++
++    if (!error_msg) {
++        error_msg = default_error_msg;
++    }
++
++    int msg_size = sizeof(StreamMsgNotifyError) + strlen(error_msg) + 1;
++    int total_size = sizeof(StreamDevHeader) + msg_size;
++
++    RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
++    RedCharDeviceWriteBuffer *buf =
++        red_char_device_write_buffer_get_server_no_token(char_dev, total_size);
++    buf->buf_used = total_size;
++
++    StreamDevHeader *const hdr = (StreamDevHeader *)buf->buf;
++    hdr->protocol_version = STREAM_DEVICE_PROTOCOL;
++    hdr->padding = 0;
++    hdr->type = GUINT16_TO_LE(STREAM_TYPE_NOTIFY_ERROR);
++    hdr->size = GUINT32_TO_LE(msg_size);
++
++    StreamMsgNotifyError *const error = (StreamMsgNotifyError *)(hdr+1);
++    error->error_code = GUINT32_TO_LE(0);
++    strcpy((char *) error->msg, error_msg);
++
++    red_char_device_write_buffer_add(char_dev, buf);
++
++    dev->has_error = true;
++    return false;
++}
++
++static bool
++handle_msg_format(StreamDevice *dev, SpiceCharDeviceInstance *sin)
++{
++    StreamMsgFormat fmt;
++    SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
++    int n = sif->read(sin, (uint8_t *) &fmt, sizeof(fmt));
++    if (n == 0) {
++        return false;
++    }
++    if (n != sizeof(fmt)) {
++        return handle_msg_invalid(dev, sin, NULL);
++    }
++    fmt.width = GUINT32_FROM_LE(fmt.width);
++    fmt.height = GUINT32_FROM_LE(fmt.height);
++
++    return true;
++}
++
++static bool
++handle_msg_data(StreamDevice *dev, SpiceCharDeviceInstance *sin)
++{
++    SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin);
++    int n;
++    while (1) {
++        uint8_t buf[16 * 1024];
+         n = sif->read(sin, buf, sizeof(buf));
++        /* TODO */
+         spice_debug("read %d bytes from device", n);
+-    } while (n > 0);
++        if (n <= 0) {
++            break;
++        }
++        dev->hdr.size -= n;
++    }
+ 
+-    return NULL;
++    return dev->hdr.size == 0;
+ }
+ 
+ static void
diff --git a/SOURCES/0008-reds-Avoid-buffer-overflows-handling-monitor-configu.patch b/SOURCES/0008-reds-Avoid-buffer-overflows-handling-monitor-configu.patch
deleted file mode 100644
index 47344b7..0000000
--- a/SOURCES/0008-reds-Avoid-buffer-overflows-handling-monitor-configu.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Frediano Ziglio <fziglio@redhat.com>
-Date: Mon, 15 May 2017 15:57:28 +0100
-Subject: [PATCH] reds: Avoid buffer overflows handling monitor configuration
-
-It was also possible for a malicious client to set
-VDAgentMonitorsConfig::num_of_monitors to a number larger
-than the actual size of VDAgentMOnitorsConfig::monitors.
-This would lead to buffer overflows, which could allow the guest to
-read part of the host memory. This might cause write overflows in the
-host as well, but controlling the content of such buffers seems
-complicated.
-
-Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
----
- server/reds.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/server/reds.c b/server/reds.c
-index eda3486..37d9da8 100644
---- a/server/reds.c
-+++ b/server/reds.c
-@@ -1000,6 +1000,7 @@ static void reds_on_main_agent_monitors_config(
-     VDAgentMessage *msg_header;
-     VDAgentMonitorsConfig *monitors_config;
-     RedsClientMonitorsConfig *cmc = &reds->client_monitors_config;
-+    uint32_t max_monitors;
- 
-     // limit size of message sent by the client as this can cause a DoS through
-     // memory exhaustion, or potentially some integer overflows
-@@ -1028,6 +1029,12 @@ static void reds_on_main_agent_monitors_config(
-         goto overflow;
-     }
-     monitors_config = (VDAgentMonitorsConfig *)(cmc->buffer + sizeof(*msg_header));
-+    // limit the monitor number to avoid buffer overflows
-+    max_monitors = (msg_header->size - sizeof(VDAgentMonitorsConfig)) /
-+                   sizeof(VDAgentMonConfig);
-+    if (monitors_config->num_of_monitors > max_monitors) {
-+        goto overflow;
-+    }
-     spice_debug("%s: %d", __func__, monitors_config->num_of_monitors);
-     red_dispatcher_client_monitors_config(monitors_config);
-     reds_client_monitors_config_cleanup();
diff --git a/SOURCES/0008-stream-channel-Write-a-base-channel-to-implement-the.patch b/SOURCES/0008-stream-channel-Write-a-base-channel-to-implement-the.patch
new file mode 100644
index 0000000..8d3b2c1
--- /dev/null
+++ b/SOURCES/0008-stream-channel-Write-a-base-channel-to-implement-the.patch
@@ -0,0 +1,271 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 15:29:18 +0000
+Subject: [spice-server] stream-channel: Write a base channel to implement the
+ streaming
+
+Currently only compile, not used and not much sense
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/Makefile.am      |   2 +
+ server/stream-channel.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++
+ server/stream-channel.h |  53 +++++++++++++++
+ 3 files changed, 230 insertions(+)
+ create mode 100644 server/stream-channel.c
+ create mode 100644 server/stream-channel.h
+
+diff --git a/server/Makefile.am b/server/Makefile.am
+index f08ddf883..e2e3ce861 100644
+--- a/server/Makefile.am
++++ b/server/Makefile.am
+@@ -166,6 +166,8 @@ libserver_la_SOURCES =				\
+ 	stat.h					\
+ 	stream.c				\
+ 	stream.h				\
++	stream-channel.c			\
++	stream-channel.h			\
+ 	stream-device.c				\
+ 	sw-canvas.c				\
+ 	tree.c					\
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+new file mode 100644
+index 000000000..fd735f562
+--- /dev/null
++++ b/server/stream-channel.c
+@@ -0,0 +1,175 @@
++/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/*
++   Copyright (C) 2017 Red Hat, Inc.
++
++   This library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   This library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with this library; if not, see <http://www.gnu.org/licenses/>.
++*/
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include "red-channel-client.h"
++#include "stream-channel.h"
++#include "reds.h"
++#include "common-graphics-channel.h"
++
++#define TYPE_STREAM_CHANNEL_CLIENT stream_channel_client_get_type()
++
++#define STREAM_CHANNEL_CLIENT(obj) \
++    (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClient))
++#define STREAM_CHANNEL_CLIENT_CLASS(klass) \
++    (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClientClass))
++#define IS_STREAM_CHANNEL_CLIENT(obj) \
++    (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_STREAM_CHANNEL_CLIENT))
++#define IS_STREAM_CHANNEL_CLIENT_CLASS(klass) \
++    (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_STREAM_CHANNEL_CLIENT))
++#define STREAM_CHANNEL_CLIENT_GET_CLASS(obj) \
++    (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClientClass))
++
++typedef struct StreamChannelClient StreamChannelClient;
++typedef struct StreamChannelClientClass StreamChannelClientClass;
++
++/* we need to inherit from CommonGraphicsChannelClient
++ * to get buffer handling */
++struct StreamChannelClient {
++    CommonGraphicsChannelClient parent;
++};
++
++struct StreamChannelClientClass {
++    CommonGraphicsChannelClientClass parent_class;
++};
++
++GType stream_channel_client_get_type(void) G_GNUC_CONST;
++
++G_DEFINE_TYPE(StreamChannelClient, stream_channel_client, TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT)
++
++struct StreamChannel {
++    RedChannel parent;
++};
++
++struct StreamChannelClass {
++    RedChannelClass parent_class;
++};
++
++G_DEFINE_TYPE(StreamChannel, stream_channel, RED_TYPE_CHANNEL)
++
++static void stream_channel_client_on_disconnect(RedChannelClient *rcc);
++
++static void
++stream_channel_client_class_init(StreamChannelClientClass *klass)
++{
++    RedChannelClientClass *channel_class = RED_CHANNEL_CLIENT_CLASS(klass);
++
++    channel_class->on_disconnect = stream_channel_client_on_disconnect;
++}
++
++static void
++stream_channel_client_init(StreamChannelClient *client)
++{
++}
++
++static void
++stream_channel_client_on_disconnect(RedChannelClient *rcc)
++{
++}
++
++static StreamChannelClient*
++stream_channel_client_new(StreamChannel *channel, RedClient *client, RedsStream *stream,
++                          int mig_target, RedChannelCapabilities *caps)
++{
++    StreamChannelClient *rcc;
++
++    rcc = g_initable_new(TYPE_STREAM_CHANNEL_CLIENT,
++                         NULL, NULL,
++                         "channel", channel,
++                         "client", client,
++                         "stream", stream,
++                         "monitor-latency", FALSE,
++                         "caps", caps,
++                         NULL);
++
++    return rcc;
++}
++
++static void
++stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
++{
++    switch (pipe_item->type) {
++    default:
++        spice_error("invalid pipe item type");
++    }
++
++    red_channel_client_begin_send_message(rcc);
++}
++
++StreamChannel*
++stream_channel_new(RedsState *server, uint32_t id)
++{
++    return g_object_new(TYPE_STREAM_CHANNEL,
++                        "spice-server", server,
++                        "core-interface", reds_get_core_interface(server),
++                        "channel-type", SPICE_CHANNEL_DISPLAY,
++                        // TODO this id should be after all qxl devices
++                        "id", id,
++                        "migration-flags", 0,
++                        "handle-acks", TRUE, // TODO sure ??
++                        NULL);
++}
++
++static void
++stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStream *stream,
++                       int migration, RedChannelCapabilities *caps)
++{
++    StreamChannel *channel = STREAM_CHANNEL(red_channel);
++    StreamChannelClient *client;
++
++    spice_return_if_fail(stream != NULL);
++
++    client = stream_channel_client_new(channel, red_client, stream, migration, caps);
++    spice_return_if_fail(client != NULL);
++}
++
++static void
++stream_channel_constructed(GObject *object)
++{
++    ClientCbs client_cbs = { NULL, };
++    RedChannel *red_channel = RED_CHANNEL(object);
++    RedsState *reds = red_channel_get_server(red_channel);
++
++    G_OBJECT_CLASS(stream_channel_parent_class)->constructed(object);
++
++    client_cbs.connect = stream_channel_connect;
++    red_channel_register_client_cbs(red_channel, &client_cbs, NULL);
++
++    reds_register_channel(reds, red_channel);
++}
++
++static void
++stream_channel_class_init(StreamChannelClass *klass)
++{
++    GObjectClass *object_class = G_OBJECT_CLASS(klass);
++    RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
++
++    object_class->constructed = stream_channel_constructed;
++
++    channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
++    channel_class->handle_message = red_channel_client_handle_message;
++
++    channel_class->send_item = stream_channel_send_item;
++}
++
++static void
++stream_channel_init(StreamChannel *channel)
++{
++}
+diff --git a/server/stream-channel.h b/server/stream-channel.h
+new file mode 100644
+index 000000000..e50e17e9e
+--- /dev/null
++++ b/server/stream-channel.h
+@@ -0,0 +1,53 @@
++/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
++/*
++   Copyright (C) 2017 Red Hat, Inc.
++
++   This library is free software; you can redistribute it and/or
++   modify it under the terms of the GNU Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 of the License, or (at your option) any later version.
++
++   This library is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with this library; if not, see <http://www.gnu.org/licenses/>.
++*/
++
++#ifndef STREAM_CHANNEL_H_
++#define STREAM_CHANNEL_H_
++
++#include "red-channel.h"
++
++G_BEGIN_DECLS
++
++/**
++ * This type it's a RedChannel class which implement display
++ * channel with input only by stream.
++ * A pointer to StreamChannel can be converted to a RedChannel.
++ */
++typedef struct StreamChannel StreamChannel;
++typedef struct StreamChannelClass StreamChannelClass;
++
++#define TYPE_STREAM_CHANNEL stream_channel_get_type()
++
++#define STREAM_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_STREAM_CHANNEL, StreamChannel))
++#define STREAM_CHANNEL_CLASS(klass) \
++    (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_STREAM_CHANNEL, StreamChannelClass))
++#define IS_STREAM_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_STREAM_CHANNEL))
++#define IS_STREAM_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_STREAM_CHANNEL))
++#define STREAM_CHANNEL_GET_CLASS(obj) \
++    (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_CHANNEL, StreamChannelClass))
++
++GType stream_channel_get_type(void) G_GNUC_CONST;
++
++/**
++ * Create StreamChannel.
++ */
++StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
++
++G_END_DECLS
++
++#endif /* STREAM_CHANNEL_H_ */
diff --git a/SOURCES/0009-stream-channel-Start-implementing-DisplayChannel-pro.patch b/SOURCES/0009-stream-channel-Start-implementing-DisplayChannel-pro.patch
new file mode 100644
index 0000000..d35ed88
--- /dev/null
+++ b/SOURCES/0009-stream-channel-Start-implementing-DisplayChannel-pro.patch
@@ -0,0 +1,88 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 14 Mar 2017 12:12:22 +0000
+Subject: [spice-server] stream-channel: Start implementing DisplayChannel
+ properly
+
+Handle messages from clients.
+Send some messages to clients.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 41 ++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 40 insertions(+), 1 deletion(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index fd735f562..df6936513 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -113,6 +113,25 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+     red_channel_client_begin_send_message(rcc);
+ }
+ 
++static bool
++handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *msg)
++{
++    switch (type) {
++    case SPICE_MSGC_DISPLAY_INIT:
++    case SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION:
++        return true;
++    case SPICE_MSGC_DISPLAY_STREAM_REPORT:
++        /* TODO these will help tune the streaming reducing/increasing quality */
++        return true;
++    case SPICE_MSGC_DISPLAY_GL_DRAW_DONE:
++        /* client should not send this message */
++        return false;
++    default:
++        return red_channel_client_handle_message(rcc, type, size, msg);
++    }
++}
++
++
+ StreamChannel*
+ stream_channel_new(RedsState *server, uint32_t id)
+ {
+@@ -138,6 +157,22 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStrea
+ 
+     client = stream_channel_client_new(channel, red_client, stream, migration, caps);
+     spice_return_if_fail(client != NULL);
++
++    // TODO set capabilities like  SPICE_DISPLAY_CAP_MONITORS_CONFIG
++    // see guest_set_client_capabilities
++    RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
++    red_channel_client_push_set_ack(rcc);
++
++    // TODO what should happen on migration, dcc return if on migration wait ??
++    red_channel_client_ack_zero_messages_window(rcc);
++
++    // "emulate" dcc_start
++    // TODO only if "surface"
++    red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
++    // TODO red_surface_create_item_new
++    // TODO surface data ??
++    // TODO monitor configs ??
++    red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_MARK);
+ }
+ 
+ static void
+@@ -152,6 +187,10 @@ stream_channel_constructed(GObject *object)
+     client_cbs.connect = stream_channel_connect;
+     red_channel_register_client_cbs(red_channel, &client_cbs, NULL);
+ 
++    // TODO, send monitor to support multiple monitors in the future
++//    red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
++    red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
++
+     reds_register_channel(reds, red_channel);
+ }
+ 
+@@ -164,7 +203,7 @@ stream_channel_class_init(StreamChannelClass *klass)
+     object_class->constructed = stream_channel_constructed;
+ 
+     channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
+-    channel_class->handle_message = red_channel_client_handle_message;
++    channel_class->handle_message = handle_message;
+ 
+     channel_class->send_item = stream_channel_send_item;
+ }
diff --git a/SOURCES/0010-stream-device-Create-channel-for-stream-device.patch b/SOURCES/0010-stream-device-Create-channel-for-stream-device.patch
new file mode 100644
index 0000000..41b7341
--- /dev/null
+++ b/SOURCES/0010-stream-device-Create-channel-for-stream-device.patch
@@ -0,0 +1,151 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 14:02:29 +0000
+Subject: [spice-server] stream-device: Create channel for stream device
+
+So can be used by the device to communicate with the clients.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++--
+ server/stream-device.c  | 14 +++++++++++++
+ 2 files changed, 64 insertions(+), 2 deletions(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index df6936513..baf3d58a6 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -19,6 +19,8 @@
+ #include <config.h>
+ #endif
+ 
++#include <common/generated_server_marshallers.h>
++
+ #include "red-channel-client.h"
+ #include "stream-channel.h"
+ #include "reds.h"
+@@ -64,6 +66,13 @@ struct StreamChannelClass {
+ 
+ G_DEFINE_TYPE(StreamChannel, stream_channel, RED_TYPE_CHANNEL)
+ 
++enum {
++    RED_PIPE_ITEM_TYPE_SURFACE_CREATE = RED_PIPE_ITEM_TYPE_COMMON_LAST,
++    RED_PIPE_ITEM_TYPE_FILL_SURFACE,
++};
++
++#define PRIMARY_SURFACE_ID 0
++
+ static void stream_channel_client_on_disconnect(RedChannelClient *rcc);
+ 
+ static void
+@@ -103,9 +112,46 @@ stream_channel_client_new(StreamChannel *channel, RedClient *client, RedsStream
+ }
+ 
+ static void
++fill_base(SpiceMarshaller *m)
++{
++    SpiceMsgDisplayBase base;
++
++    base.surface_id = PRIMARY_SURFACE_ID;
++    base.box = (SpiceRect) { 0, 0, 1024, 768 };
++    base.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
++
++    spice_marshall_DisplayBase(m, &base);
++}
++
++static void
+ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+ {
++    SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
++
+     switch (pipe_item->type) {
++    case RED_PIPE_ITEM_TYPE_SURFACE_CREATE: {
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_SURFACE_CREATE);
++        SpiceMsgSurfaceCreate surface_create = {
++            PRIMARY_SURFACE_ID,
++            1024, 768,
++            SPICE_SURFACE_FMT_32_xRGB, SPICE_SURFACE_FLAGS_PRIMARY
++        };
++        spice_marshall_msg_display_surface_create(m, &surface_create);
++        break;
++    }
++    case RED_PIPE_ITEM_TYPE_FILL_SURFACE: {
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_FILL);
++
++        fill_base(m);
++
++        SpiceFill fill;
++        fill.brush = (SpiceBrush) { SPICE_BRUSH_TYPE_SOLID, { .color = 0 } };
++        fill.rop_descriptor = SPICE_ROPD_OP_PUT;
++        fill.mask = (SpiceQMask) { 0, { 0, 0 }, NULL };
++        SpiceMarshaller *brush_pat_out, *mask_bitmap_out;
++        spice_marshall_Fill(m, &fill, &brush_pat_out, &mask_bitmap_out);
++        break;
++    }
+     default:
+         spice_error("invalid pipe item type");
+     }
+@@ -169,8 +215,10 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStrea
+     // "emulate" dcc_start
+     // TODO only if "surface"
+     red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
+-    // TODO red_surface_create_item_new
+-    // TODO surface data ??
++    // TODO pass proper data
++    red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_SURFACE_CREATE);
++    // surface data
++    red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_FILL_SURFACE);
+     // TODO monitor configs ??
+     red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_MARK);
+ }
+diff --git a/server/stream-device.c b/server/stream-device.c
+index 58edb3d11..0c9173ae0 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -22,6 +22,8 @@
+ #include <spice/stream-device.h>
+ 
+ #include "char-device.h"
++#include "stream-channel.h"
++#include "reds.h"
+ 
+ #define TYPE_STREAM_DEVICE stream_device_get_type()
+ 
+@@ -37,9 +39,11 @@ typedef struct StreamDeviceClass StreamDeviceClass;
+ 
+ struct StreamDevice {
+     RedCharDevice parent;
++
+     StreamDevHeader hdr;
+     uint8_t hdr_pos;
+     bool has_error;
++    StreamChannel *stream_channel;
+ };
+ 
+ struct StreamDeviceClass {
+@@ -204,7 +208,10 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ {
+     SpiceCharDeviceInterface *sif;
+ 
++    StreamChannel *stream_channel = stream_channel_new(reds, 1); // TODO id
++
+     StreamDevice *dev = stream_device_new(sin, reds);
++    dev->stream_channel = stream_channel;
+ 
+     sif = spice_char_device_get_interface(sin);
+     if (sif->state) {
+@@ -217,6 +224,13 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ static void
+ stream_device_dispose(GObject *object)
+ {
++    StreamDevice *dev = STREAM_DEVICE(object);
++
++    if (dev->stream_channel) {
++        // close all current connections and drop the reference
++        red_channel_destroy(RED_CHANNEL(dev->stream_channel));
++        dev->stream_channel = NULL;
++    }
+ }
+ 
+ static void
diff --git a/SOURCES/0011-stream-device-Handle-streaming-data-from-device-to-c.patch b/SOURCES/0011-stream-device-Handle-streaming-data-from-device-to-c.patch
new file mode 100644
index 0000000..2e53f13
--- /dev/null
+++ b/SOURCES/0011-stream-device-Handle-streaming-data-from-device-to-c.patch
@@ -0,0 +1,231 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 10:47:40 +0000
+Subject: [spice-server] stream-device: Handle streaming data from device to
+ channel
+
+Handle stream data from device sending to the channel.
+The StreamChannel will forward the data to the clients using standard
+DisplayChannel messages, and will create and destroy streams as
+necessary.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++
+ server/stream-channel.h |   8 ++++
+ server/stream-device.c  |   4 +-
+ 3 files changed, 113 insertions(+), 2 deletions(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index baf3d58a6..8931d8794 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -20,11 +20,13 @@
+ #endif
+ 
+ #include <common/generated_server_marshallers.h>
++#include <spice/stream-device.h>
+ 
+ #include "red-channel-client.h"
+ #include "stream-channel.h"
+ #include "reds.h"
+ #include "common-graphics-channel.h"
++#include "display-limits.h"
+ 
+ #define TYPE_STREAM_CHANNEL_CLIENT stream_channel_client_get_type()
+ 
+@@ -46,6 +48,10 @@ typedef struct StreamChannelClientClass StreamChannelClientClass;
+  * to get buffer handling */
+ struct StreamChannelClient {
+     CommonGraphicsChannelClient parent;
++
++    /* current video stream id, <0 if not initialized or
++     * we are not sending a stream */
++    int stream_id;
+ };
+ 
+ struct StreamChannelClientClass {
+@@ -58,6 +64,10 @@ G_DEFINE_TYPE(StreamChannelClient, stream_channel_client, TYPE_COMMON_GRAPHICS_C
+ 
+ struct StreamChannel {
+     RedChannel parent;
++
++    /* current video stream id, <0 if not initialized or
++     * we are not sending a stream */
++    int stream_id;
+ };
+ 
+ struct StreamChannelClass {
+@@ -69,8 +79,22 @@ G_DEFINE_TYPE(StreamChannel, stream_channel, RED_TYPE_CHANNEL)
+ enum {
+     RED_PIPE_ITEM_TYPE_SURFACE_CREATE = RED_PIPE_ITEM_TYPE_COMMON_LAST,
+     RED_PIPE_ITEM_TYPE_FILL_SURFACE,
++    RED_PIPE_ITEM_TYPE_STREAM_CREATE,
++    RED_PIPE_ITEM_TYPE_STREAM_DATA,
++    RED_PIPE_ITEM_TYPE_STREAM_DESTROY,
+ };
+ 
++typedef struct StreamCreateItem {
++    RedPipeItem base;
++    SpiceMsgDisplayStreamCreate stream_create;
++} StreamCreateItem;
++
++typedef struct StreamDataItem {
++    RedPipeItem base;
++    // NOTE: this must be the last field in the structure
++    SpiceMsgDisplayStreamData data;
++} StreamDataItem;
++
+ #define PRIMARY_SURFACE_ID 0
+ 
+ static void stream_channel_client_on_disconnect(RedChannelClient *rcc);
+@@ -86,6 +110,7 @@ stream_channel_client_class_init(StreamChannelClientClass *klass)
+ static void
+ stream_channel_client_init(StreamChannelClient *client)
+ {
++    client->stream_id = -1;
+ }
+ 
+ static void
+@@ -127,6 +152,7 @@ static void
+ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+ {
+     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
++    StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
+ 
+     switch (pipe_item->type) {
+     case RED_PIPE_ITEM_TYPE_SURFACE_CREATE: {
+@@ -152,6 +178,32 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+         spice_marshall_Fill(m, &fill, &brush_pat_out, &mask_bitmap_out);
+         break;
+     }
++    case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
++        StreamCreateItem *item = SPICE_UPCAST(StreamCreateItem, pipe_item);
++        client->stream_id = item->stream_create.id;
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CREATE);
++        spice_marshall_msg_display_stream_create(m, &item->stream_create);
++        break;
++    }
++    case RED_PIPE_ITEM_TYPE_STREAM_DATA: {
++        StreamDataItem *item = SPICE_UPCAST(StreamDataItem, pipe_item);
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA);
++        spice_marshall_msg_display_stream_data(m, &item->data);
++        red_pipe_item_ref(pipe_item);
++        spice_marshaller_add_by_ref_full(m, item->data.data, item->data.data_size,
++                                         marshaller_unref_pipe_item, pipe_item);
++        break;
++    }
++    case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
++        if (client->stream_id < 0) {
++            return;
++        }
++        SpiceMsgDisplayStreamDestroy stream_destroy = { client->stream_id };
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY);
++        spice_marshall_msg_display_stream_destroy(m, &stream_destroy);
++        client->stream_id = -1;
++        break;
++    }
+     default:
+         spice_error("invalid pipe item type");
+     }
+@@ -259,4 +311,55 @@ stream_channel_class_init(StreamChannelClass *klass)
+ static void
+ stream_channel_init(StreamChannel *channel)
+ {
++    channel->stream_id = -1;
++}
++
++void
++stream_channel_change_format(StreamChannel *channel, const StreamMsgFormat *fmt)
++{
++    RedChannel *red_channel = RED_CHANNEL(channel);
++
++    // send destroy old stream
++    red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
++
++    // TODO send new create surface if required
++
++    // allocate a new stream id
++    channel->stream_id = (channel->stream_id + 1) % NUM_STREAMS;
++
++    // send create stream
++    StreamCreateItem *item = g_new0(StreamCreateItem, 1);
++    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
++    item->stream_create.id = channel->stream_id;
++    item->stream_create.flags = SPICE_STREAM_FLAGS_TOP_DOWN;
++    item->stream_create.codec_type = fmt->codec;
++    item->stream_create.stream_width = fmt->width;
++    item->stream_create.stream_height = fmt->height;
++    item->stream_create.src_width = fmt->width;
++    item->stream_create.src_height = fmt->height;
++    item->stream_create.dest = (SpiceRect) { 0, 0, fmt->width, fmt->height };
++    item->stream_create.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
++    red_channel_pipes_add(red_channel, &item->base);
++}
++
++void
++stream_channel_send_data(StreamChannel *channel, const void *data, size_t size, uint32_t mm_time)
++{
++    if (channel->stream_id < 0) {
++        // this condition can happen if the guest didn't handle
++        // the format stop that we send so think the stream is still
++        // started
++        return;
++    }
++
++    RedChannel *red_channel = RED_CHANNEL(channel);
++
++    StreamDataItem *item = g_malloc(sizeof(*item) + size);
++    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_DATA);
++    item->data.base.id = channel->stream_id;
++    item->data.base.multi_media_time = mm_time;
++    item->data.data_size = size;
++    // TODO try to optimize avoiding the copy
++    memcpy(item->data.data, data, size);
++    red_channel_pipes_add(red_channel, &item->base);
+ }
+diff --git a/server/stream-channel.h b/server/stream-channel.h
+index e50e17e9e..156a75d31 100644
+--- a/server/stream-channel.h
++++ b/server/stream-channel.h
+@@ -48,6 +48,14 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
+  */
+ StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
+ 
++struct StreamMsgFormat;
++
++void stream_channel_change_format(StreamChannel *channel,
++                                  const struct StreamMsgFormat *fmt);
++void stream_channel_send_data(StreamChannel *channel,
++                              const void *data, size_t size,
++                              uint32_t mm_time);
++
+ G_END_DECLS
+ 
+ #endif /* STREAM_CHANNEL_H_ */
+diff --git a/server/stream-device.c b/server/stream-device.c
+index 0c9173ae0..6e78b1a99 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -164,6 +164,7 @@ handle_msg_format(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+     }
+     fmt.width = GUINT32_FROM_LE(fmt.width);
+     fmt.height = GUINT32_FROM_LE(fmt.height);
++    stream_channel_change_format(dev->stream_channel, &fmt);
+ 
+     return true;
+ }
+@@ -176,11 +177,10 @@ handle_msg_data(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+     while (1) {
+         uint8_t buf[16 * 1024];
+         n = sif->read(sin, buf, sizeof(buf));
+-        /* TODO */
+-        spice_debug("read %d bytes from device", n);
+         if (n <= 0) {
+             break;
+         }
++        stream_channel_send_data(dev->stream_channel, buf, n, reds_get_mm_time());
+         dev->hdr.size -= n;
+     }
+ 
diff --git a/SOURCES/0012-stream-channel-Allows-not-fixed-size.patch b/SOURCES/0012-stream-channel-Allows-not-fixed-size.patch
new file mode 100644
index 0000000..354002e
--- /dev/null
+++ b/SOURCES/0012-stream-channel-Allows-not-fixed-size.patch
@@ -0,0 +1,115 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 19:03:11 +0000
+Subject: [spice-server] stream-channel: Allows not fixed size
+
+Remove the fixed size stream and support any display size.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 31 +++++++++++++++++++++++++------
+ 1 file changed, 25 insertions(+), 6 deletions(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index 8931d8794..59f566f50 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -68,6 +68,8 @@ struct StreamChannel {
+     /* current video stream id, <0 if not initialized or
+      * we are not sending a stream */
+     int stream_id;
++    /* size of the current video stream */
++    unsigned width, height;
+ };
+ 
+ struct StreamChannelClass {
+@@ -78,6 +80,7 @@ G_DEFINE_TYPE(StreamChannel, stream_channel, RED_TYPE_CHANNEL)
+ 
+ enum {
+     RED_PIPE_ITEM_TYPE_SURFACE_CREATE = RED_PIPE_ITEM_TYPE_COMMON_LAST,
++    RED_PIPE_ITEM_TYPE_SURFACE_DESTROY,
+     RED_PIPE_ITEM_TYPE_FILL_SURFACE,
+     RED_PIPE_ITEM_TYPE_STREAM_CREATE,
+     RED_PIPE_ITEM_TYPE_STREAM_DATA,
+@@ -137,12 +140,12 @@ stream_channel_client_new(StreamChannel *channel, RedClient *client, RedsStream
+ }
+ 
+ static void
+-fill_base(SpiceMarshaller *m)
++fill_base(SpiceMarshaller *m, const StreamChannel *channel)
+ {
+     SpiceMsgDisplayBase base;
+ 
+     base.surface_id = PRIMARY_SURFACE_ID;
+-    base.box = (SpiceRect) { 0, 0, 1024, 768 };
++    base.box = (SpiceRect) { 0, 0, channel->width, channel->height };
+     base.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
+ 
+     spice_marshall_DisplayBase(m, &base);
+@@ -153,22 +156,29 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+ {
+     SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
+     StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
++    StreamChannel *channel = STREAM_CHANNEL(red_channel_client_get_channel(rcc));
+ 
+     switch (pipe_item->type) {
+     case RED_PIPE_ITEM_TYPE_SURFACE_CREATE: {
+         red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_SURFACE_CREATE);
+         SpiceMsgSurfaceCreate surface_create = {
+             PRIMARY_SURFACE_ID,
+-            1024, 768,
++            channel->width, channel->height,
+             SPICE_SURFACE_FMT_32_xRGB, SPICE_SURFACE_FLAGS_PRIMARY
+         };
+         spice_marshall_msg_display_surface_create(m, &surface_create);
+         break;
+     }
++    case RED_PIPE_ITEM_TYPE_SURFACE_DESTROY: {
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_SURFACE_DESTROY);
++        SpiceMsgSurfaceDestroy surface_destroy = { PRIMARY_SURFACE_ID };
++        spice_marshall_msg_display_surface_destroy(m, &surface_destroy);
++        break;
++    }
+     case RED_PIPE_ITEM_TYPE_FILL_SURFACE: {
+         red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_FILL);
+ 
+-        fill_base(m);
++        fill_base(m, channel);
+ 
+         SpiceFill fill;
+         fill.brush = (SpiceBrush) { SPICE_BRUSH_TYPE_SOLID, { .color = 0 } };
+@@ -267,7 +277,7 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStrea
+     // "emulate" dcc_start
+     // TODO only if "surface"
+     red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
+-    // TODO pass proper data
++    // pass proper data
+     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_SURFACE_CREATE);
+     // surface data
+     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_FILL_SURFACE);
+@@ -312,6 +322,8 @@ static void
+ stream_channel_init(StreamChannel *channel)
+ {
+     channel->stream_id = -1;
++    channel->width = 1024;
++    channel->height = 768;
+ }
+ 
+ void
+@@ -322,7 +334,14 @@ stream_channel_change_format(StreamChannel *channel, const StreamMsgFormat *fmt)
+     // send destroy old stream
+     red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
+ 
+-    // TODO send new create surface if required
++    // send new create surface if required
++    if (channel->width != fmt->width || channel->height != fmt->height) {
++        channel->width = fmt->width;
++        channel->height = fmt->height;
++        red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
++        red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_CREATE);
++        // TODO monitors config ??
++    }
+ 
+     // allocate a new stream id
+     channel->stream_id = (channel->stream_id + 1) % NUM_STREAMS;
diff --git a/SOURCES/0013-stream-channel-Allows-to-register-callback-to-get-ne.patch b/SOURCES/0013-stream-channel-Allows-to-register-callback-to-get-ne.patch
new file mode 100644
index 0000000..7ed0b16
--- /dev/null
+++ b/SOURCES/0013-stream-channel-Allows-to-register-callback-to-get-ne.patch
@@ -0,0 +1,67 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 19:08:12 +0000
+Subject: [spice-server] stream-channel: Allows to register callback to get new
+ stream request
+
+The channel needs to communicate when it receive a new
+stream request from the guest.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 12 ++++++++++++
+ server/stream-channel.h |  6 ++++++
+ 2 files changed, 18 insertions(+)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index 59f566f50..be6f7c7d1 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -70,6 +70,10 @@ struct StreamChannel {
+     int stream_id;
+     /* size of the current video stream */
+     unsigned width, height;
++
++    /* callback to notify when a stream should be started or stopped */
++    stream_channel_start_proc start_cb;
++    void *start_opaque;
+ };
+ 
+ struct StreamChannelClass {
+@@ -382,3 +386,11 @@ stream_channel_send_data(StreamChannel *channel, const void *data, size_t size,
+     memcpy(item->data.data, data, size);
+     red_channel_pipes_add(red_channel, &item->base);
+ }
++
++void
++stream_channel_register_start_cb(StreamChannel *channel,
++                                 stream_channel_start_proc cb, void *opaque)
++{
++    channel->start_cb = cb;
++    channel->start_opaque = opaque;
++}
+diff --git a/server/stream-channel.h b/server/stream-channel.h
+index 156a75d31..ba098df49 100644
+--- a/server/stream-channel.h
++++ b/server/stream-channel.h
+@@ -49,6 +49,7 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
+ StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
+ 
+ struct StreamMsgFormat;
++struct StreamMsgStartStop;
+ 
+ void stream_channel_change_format(StreamChannel *channel,
+                                   const struct StreamMsgFormat *fmt);
+@@ -56,6 +57,11 @@ void stream_channel_send_data(StreamChannel *channel,
+                               const void *data, size_t size,
+                               uint32_t mm_time);
+ 
++typedef void (*stream_channel_start_proc)(void *opaque, struct StreamMsgStartStop *start,
++                                          StreamChannel *channel);
++void stream_channel_register_start_cb(StreamChannel *channel,
++                                      stream_channel_start_proc cb, void *opaque);
++
+ G_END_DECLS
+ 
+ #endif /* STREAM_CHANNEL_H_ */
diff --git a/SOURCES/0014-stream-channel-Support-client-connection-disconnecti.patch b/SOURCES/0014-stream-channel-Support-client-connection-disconnecti.patch
new file mode 100644
index 0000000..d71ee50
--- /dev/null
+++ b/SOURCES/0014-stream-channel-Support-client-connection-disconnecti.patch
@@ -0,0 +1,131 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 19:03:19 +0000
+Subject: [spice-server] stream-channel: Support client
+ connection/disconnection
+
+When a new client is connected we must restart the stream so new
+clients can receive correct data without having to wait for the
+next full screen (which on idle screen could take ages).
+On disconnection we should tell the guest to stop streaming
+not wasting resources to stream not needed data.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 81 insertions(+)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index be6f7c7d1..2ad9ebae3 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -121,8 +121,32 @@ stream_channel_client_init(StreamChannelClient *client)
+ }
+ 
+ static void
++request_new_stream(StreamChannel *channel, StreamMsgStartStop *start)
++{
++    if (channel->start_cb) {
++        channel->start_cb(channel->start_opaque, start, channel);
++    }
++}
++
++static void
+ stream_channel_client_on_disconnect(RedChannelClient *rcc)
+ {
++    RedChannel *red_channel = red_channel_client_get_channel(rcc);
++
++    // if there are still some client connected keep streaming
++    // TODO, maybe would be worth sending new codecs if they are better
++    if (red_channel_is_connected(red_channel)) {
++        return;
++    }
++
++    StreamChannel *channel = STREAM_CHANNEL(red_channel);
++    channel->stream_id = -1;
++    channel->width = 0;
++    channel->height = 0;
++
++    // send stream stop to device
++    StreamMsgStartStop stop = { 0, };
++    request_new_stream(channel, &stop);
+ }
+ 
+ static StreamChannelClient*
+@@ -258,18 +282,75 @@ stream_channel_new(RedsState *server, uint32_t id)
+                         NULL);
+ }
+ 
++#define MAX_SUPPORTED_CODECS SPICE_VIDEO_CODEC_TYPE_ENUM_END
++
++// find common codecs supported by all clients
++static uint8_t
++stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs)
++{
++    RedChannelClient *rcc;
++    int codec;
++
++    static const uint16_t codec2cap[] = {
++        0, // invalid
++        SPICE_DISPLAY_CAP_CODEC_MJPEG,
++        SPICE_DISPLAY_CAP_CODEC_VP8,
++        SPICE_DISPLAY_CAP_CODEC_H264,
++        SPICE_DISPLAY_CAP_CODEC_VP9,
++    };
++
++    bool supported[SPICE_N_ELEMENTS(codec2cap)];
++
++    for (codec = 0; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
++        supported[codec] = true;
++    }
++
++    FOREACH_CLIENT(channel, rcc) {
++        for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
++            // if do not support codec delete from list
++            if (!red_channel_client_test_remote_cap(rcc, codec2cap[codec])) {
++                supported[codec] = false;
++            }
++        }
++    }
++
++    // surely mjpeg is supported
++    supported[SPICE_VIDEO_CODEC_TYPE_MJPEG] = true;
++
++    int num = 0;
++    for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
++        if (supported[codec]) {
++            out_codecs[num++] = codec;
++        }
++    }
++
++    return num;
++}
++
+ static void
+ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStream *stream,
+                        int migration, RedChannelCapabilities *caps)
+ {
+     StreamChannel *channel = STREAM_CHANNEL(red_channel);
+     StreamChannelClient *client;
++    struct {
++        StreamMsgStartStop base;
++        uint8_t codecs_buffer[MAX_SUPPORTED_CODECS];
++    } start_msg;
++    StreamMsgStartStop *const start = &start_msg.base;
+ 
+     spice_return_if_fail(stream != NULL);
+ 
+     client = stream_channel_client_new(channel, red_client, stream, migration, caps);
+     spice_return_if_fail(client != NULL);
+ 
++    // request new stream
++    start->num_codecs = stream_channel_get_supported_codecs(channel, start->codecs);
++    // send in any case, even if list is not changed
++    // notify device about changes
++    request_new_stream(channel, start);
++
++
+     // TODO set capabilities like  SPICE_DISPLAY_CAP_MONITORS_CONFIG
+     // see guest_set_client_capabilities
+     RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
diff --git a/SOURCES/0015-stream-channel-Do-not-show-an-empty-blank-screen-on-.patch b/SOURCES/0015-stream-channel-Do-not-show-an-empty-blank-screen-on-.patch
new file mode 100644
index 0000000..8d52cf4
--- /dev/null
+++ b/SOURCES/0015-stream-channel-Do-not-show-an-empty-blank-screen-on-.patch
@@ -0,0 +1,64 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Sat, 21 Jan 2017 09:01:18 +0000
+Subject: [spice-server] stream-channel: Do not show an empty blank screen on
+ start
+
+Start showing something when we have a surface and stream
+instead of showing a blank screen which is now not useful.
+Was useful for debugging purposes to understand that the
+new channel was sending messages correctly to client and
+client could handle them.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index 2ad9ebae3..e89563b82 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -360,8 +360,13 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStrea
+     red_channel_client_ack_zero_messages_window(rcc);
+ 
+     // "emulate" dcc_start
+-    // TODO only if "surface"
+     red_channel_client_pipe_add_empty_msg(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
++
++    // only if "surface"
++    if (channel->width == 0 || channel->height == 0) {
++        return;
++    }
++
+     // pass proper data
+     red_channel_client_pipe_add_type(rcc, RED_PIPE_ITEM_TYPE_SURFACE_CREATE);
+     // surface data
+@@ -407,8 +412,8 @@ static void
+ stream_channel_init(StreamChannel *channel)
+ {
+     channel->stream_id = -1;
+-    channel->width = 1024;
+-    channel->height = 768;
++    channel->width = 0;
++    channel->height = 0;
+ }
+ 
+ void
+@@ -421,11 +426,14 @@ stream_channel_change_format(StreamChannel *channel, const StreamMsgFormat *fmt)
+ 
+     // send new create surface if required
+     if (channel->width != fmt->width || channel->height != fmt->height) {
++        if (channel->width != 0 && channel->height != 0) {
++            red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
++        }
+         channel->width = fmt->width;
+         channel->height = fmt->height;
+-        red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
+         red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_CREATE);
+         // TODO monitors config ??
++        red_channel_pipes_add_empty_msg(red_channel, SPICE_MSG_DISPLAY_MARK);
+     }
+ 
+     // allocate a new stream id
diff --git a/SOURCES/0016-char-device-Do-not-stop-and-clear-interface-on-reset.patch b/SOURCES/0016-char-device-Do-not-stop-and-clear-interface-on-reset.patch
new file mode 100644
index 0000000..adb8442
--- /dev/null
+++ b/SOURCES/0016-char-device-Do-not-stop-and-clear-interface-on-reset.patch
@@ -0,0 +1,67 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Tue, 24 Jan 2017 11:36:27 +0000
+Subject: [spice-server] char-device: Do not stop and clear interface on reset
+
+Currently, red_char_device_reset() stops the device, clears all pending
+messages, and clears its device instance. After this function is called,
+the char device will not work again until it is assigned a new device
+instance and restarted. This is fine for the vdagent char device, which
+is currently the only user of this function. But for the stream device,
+we want to be able to reset the char device to a working state (e.g.
+clear all pending messages, etc) without stopping or disabling the char
+device. So this function will now only reset the char device to a clean
+working state, and the _stop() and _reset_dev_instance() calls will be
+moved up to the caller.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/char-device.c | 2 --
+ server/reds.c        | 6 +++++-
+ 2 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/server/char-device.c b/server/char-device.c
+index 658f9f364..f8a098bd8 100644
+--- a/server/char-device.c
++++ b/server/char-device.c
+@@ -823,7 +823,6 @@ void red_char_device_reset(RedCharDevice *dev)
+     GList *client_item;
+     RedCharDeviceWriteBuffer *buf;
+ 
+-    red_char_device_stop(dev);
+     dev->priv->wait_for_migrate_data = FALSE;
+     spice_debug("char device %p", dev);
+     while ((buf = g_queue_pop_tail(&dev->priv->write_queue))) {
+@@ -845,7 +844,6 @@ void red_char_device_reset(RedCharDevice *dev)
+         dev_client->num_client_tokens += dev_client->num_client_tokens_free;
+         dev_client->num_client_tokens_free = 0;
+     }
+-    red_char_device_reset_dev_instance(dev, NULL);
+ }
+ 
+ void red_char_device_wakeup(RedCharDevice *dev)
+diff --git a/server/reds.c b/server/reds.c
+index b24f61ab2..401d242fb 100644
+--- a/server/reds.c
++++ b/server/reds.c
+@@ -470,6 +470,7 @@ static void reds_reset_vdp(RedsState *reds)
+ {
+     RedCharDeviceVDIPort *dev = reds->agent_dev;
+     SpiceCharDeviceInterface *sif;
++    RedCharDevice *char_dev;
+ 
+     dev->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
+     dev->priv->receive_pos = (uint8_t *)&dev->priv->vdi_chunk_header;
+@@ -502,7 +503,10 @@ static void reds_reset_vdp(RedsState *reds)
+      *  The tokens are also reset to avoid mismatch in upon agent reconnection.
+      */
+     dev->priv->agent_attached = FALSE;
+-    red_char_device_reset(RED_CHAR_DEVICE(dev));
++    char_dev = RED_CHAR_DEVICE(dev);
++    red_char_device_stop(char_dev);
++    red_char_device_reset(char_dev);
++    red_char_device_reset_dev_instance(char_dev, NULL);
+ 
+     sif = spice_char_device_get_interface(reds->vdagent);
+     if (sif->state) {
diff --git a/SOURCES/0017-stream-device-Start-supporting-resetting-device-when.patch b/SOURCES/0017-stream-device-Start-supporting-resetting-device-when.patch
new file mode 100644
index 0000000..b26eb53
--- /dev/null
+++ b/SOURCES/0017-stream-device-Start-supporting-resetting-device-when.patch
@@ -0,0 +1,166 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 25 Jan 2017 22:42:00 +0000
+Subject: [spice-server] stream-device: Start supporting resetting device when
+ close/open on guest
+
+When guest close the device the host device has to be reset too.
+This make easier to restart the guest device which can happen in case
+of reboot, agent issues or if we want to update the agent.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 34 ++++++++++++++++++++++++++++++++++
+ server/stream-channel.h |  7 ++++++-
+ server/stream-device.c  | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 89 insertions(+), 1 deletion(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index e89563b82..51b8badf9 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -483,3 +483,37 @@ stream_channel_register_start_cb(StreamChannel *channel,
+     channel->start_cb = cb;
+     channel->start_opaque = opaque;
+ }
++
++void
++stream_channel_reset(StreamChannel *channel)
++{
++    struct {
++        StreamMsgStartStop base;
++        uint8_t codecs_buffer[MAX_SUPPORTED_CODECS];
++    } start_msg;
++    StreamMsgStartStop *const start = &start_msg.base;
++    RedChannel *red_channel = RED_CHANNEL(channel);
++
++    // send destroy old stream
++    red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_DESTROY);
++
++    // destroy display surface
++    if (channel->width != 0 && channel->height != 0) {
++        red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_SURFACE_DESTROY);
++    }
++
++    channel->stream_id = -1;
++    channel->width = 0;
++    channel->height = 0;
++
++    if (!red_channel_is_connected(red_channel)) {
++        return;
++    }
++
++    // try to request a new stream, this should start a new stream
++    // if the guest is connected to the device and a client is already connected
++    start->num_codecs = stream_channel_get_supported_codecs(channel, start->codecs);
++    // send in any case, even if list is not changed
++    // notify device about changes
++    request_new_stream(channel, start);
++}
+diff --git a/server/stream-channel.h b/server/stream-channel.h
+index ba098df49..bd075a951 100644
+--- a/server/stream-channel.h
++++ b/server/stream-channel.h
+@@ -48,7 +48,12 @@ GType stream_channel_get_type(void) G_GNUC_CONST;
+  */
+ StreamChannel* stream_channel_new(RedsState *server, uint32_t id);
+ 
+-struct StreamMsgFormat;
++/**
++ * Reset channel at initial state
++ */
++void stream_channel_reset(StreamChannel *channel);
++
++struct StreamMsgStreamFormat;
+ struct StreamMsgStartStop;
+ 
+ void stream_channel_change_format(StreamChannel *channel,
+diff --git a/server/stream-device.c b/server/stream-device.c
+index 6e78b1a99..9e401f8ed 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -43,6 +43,7 @@ struct StreamDevice {
+     StreamDevHeader hdr;
+     uint8_t hdr_pos;
+     bool has_error;
++    bool opened;
+     StreamChannel *stream_channel;
+ };
+ 
+@@ -203,6 +204,35 @@ stream_device_remove_client(RedCharDevice *self, RedClient *client)
+ {
+ }
+ 
++static void
++stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
++                           StreamChannel *stream_channel G_GNUC_UNUSED)
++{
++    StreamDevice *dev = (StreamDevice *) opaque;
++
++    if (!dev->opened) {
++        return;
++    }
++
++    int msg_size = sizeof(*start) + sizeof(start->codecs[0]) * start->num_codecs;
++    int total_size = sizeof(StreamDevHeader) + msg_size;
++
++    RedCharDevice *char_dev = RED_CHAR_DEVICE(dev);
++    RedCharDeviceWriteBuffer *buf =
++        red_char_device_write_buffer_get_server_no_token(char_dev, total_size);
++    buf->buf_used = total_size;
++
++    StreamDevHeader *hdr = (StreamDevHeader *)buf->buf;
++    hdr->protocol_version = STREAM_DEVICE_PROTOCOL;
++    hdr->padding = 0;
++    hdr->type = GUINT16_TO_LE(STREAM_TYPE_START_STOP);
++    hdr->size = GUINT32_TO_LE(msg_size);
++
++    memcpy(&hdr[1], start, msg_size);
++
++    red_char_device_write_buffer_add(char_dev, buf);
++}
++
+ RedCharDevice *
+ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ {
+@@ -212,6 +242,7 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ 
+     StreamDevice *dev = stream_device_new(sin, reds);
+     dev->stream_channel = stream_channel;
++    stream_channel_register_start_cb(stream_channel, stream_device_stream_start, dev);
+ 
+     sif = spice_char_device_get_interface(sin);
+     if (sif->state) {
+@@ -234,6 +265,23 @@ stream_device_dispose(GObject *object)
+ }
+ 
+ static void
++stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
++{
++    if (event != SPICE_PORT_EVENT_OPENED && event != SPICE_PORT_EVENT_CLOSED) {
++        return;
++    }
++
++    StreamDevice *dev = STREAM_DEVICE(char_dev);
++
++    // reset device and channel on close/open
++    dev->opened = (event == SPICE_PORT_EVENT_OPENED);
++    dev->hdr_pos = 0;
++    dev->has_error = false;
++    red_char_device_reset(char_dev);
++    stream_channel_reset(dev->stream_channel);
++}
++
++static void
+ stream_device_class_init(StreamDeviceClass *klass)
+ {
+     GObjectClass *object_class = G_OBJECT_CLASS(klass);
+@@ -245,6 +293,7 @@ stream_device_class_init(StreamDeviceClass *klass)
+     char_dev_class->send_msg_to_client = stream_device_send_msg_to_client;
+     char_dev_class->send_tokens_to_client = stream_device_send_tokens_to_client;
+     char_dev_class->remove_client = stream_device_remove_client;
++    char_dev_class->port_event = stream_device_port_event;
+ }
+ 
+ static void
diff --git a/SOURCES/0018-stream-device-Create-channel-when-needed.patch b/SOURCES/0018-stream-device-Create-channel-when-needed.patch
new file mode 100644
index 0000000..5d9cec6
--- /dev/null
+++ b/SOURCES/0018-stream-device-Create-channel-when-needed.patch
@@ -0,0 +1,89 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Fri, 25 Aug 2017 00:02:54 +0100
+Subject: [spice-server] stream-device: Create channel when needed
+
+This allows a better id allocation as devices are created after
+fixed ones.
+Also will allow to support more easily multiple monitor.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-device.c | 38 ++++++++++++++++++++++++++++++++------
+ 1 file changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/server/stream-device.c b/server/stream-device.c
+index 9e401f8ed..ae108788b 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -72,7 +72,7 @@ stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *si
+     int n;
+     bool handled = false;
+ 
+-    if (dev->has_error) {
++    if (dev->has_error || !dev->stream_channel) {
+         return NULL;
+     }
+ 
+@@ -238,11 +238,7 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ {
+     SpiceCharDeviceInterface *sif;
+ 
+-    StreamChannel *stream_channel = stream_channel_new(reds, 1); // TODO id
+-
+     StreamDevice *dev = stream_device_new(sin, reds);
+-    dev->stream_channel = stream_channel;
+-    stream_channel_register_start_cb(stream_channel, stream_device_stream_start, dev);
+ 
+     sif = spice_char_device_get_interface(sin);
+     if (sif->state) {
+@@ -265,6 +261,33 @@ stream_device_dispose(GObject *object)
+ }
+ 
+ static void
++allocate_channels(StreamDevice *dev)
++{
++    if (dev->stream_channel) {
++        return;
++    }
++
++    SpiceServer* reds = red_char_device_get_server(RED_CHAR_DEVICE(dev));
++
++    int id = reds_get_free_channel_id(reds, SPICE_CHANNEL_DISPLAY);
++    g_return_if_fail(id >= 0);
++
++    StreamChannel *stream_channel = stream_channel_new(reds, id);
++
++    dev->stream_channel = stream_channel;
++
++    stream_channel_register_start_cb(stream_channel, stream_device_stream_start, dev);
++}
++
++static void
++reset_channels(StreamDevice *dev)
++{
++    if (dev->stream_channel) {
++        stream_channel_reset(dev->stream_channel);
++    }
++}
++
++static void
+ stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
+ {
+     if (event != SPICE_PORT_EVENT_OPENED && event != SPICE_PORT_EVENT_CLOSED) {
+@@ -275,10 +298,13 @@ stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
+ 
+     // reset device and channel on close/open
+     dev->opened = (event == SPICE_PORT_EVENT_OPENED);
++    if (dev->opened) {
++        allocate_channels(dev);
++    }
+     dev->hdr_pos = 0;
+     dev->has_error = false;
+     red_char_device_reset(char_dev);
+-    stream_channel_reset(dev->stream_channel);
++    reset_channels(dev);
+ }
+ 
+ static void
diff --git a/SOURCES/0019-stream-device-Limit-sending-queue-from-guest-to-serv.patch b/SOURCES/0019-stream-device-Limit-sending-queue-from-guest-to-serv.patch
new file mode 100644
index 0000000..a242052
--- /dev/null
+++ b/SOURCES/0019-stream-device-Limit-sending-queue-from-guest-to-serv.patch
@@ -0,0 +1,206 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 19 Apr 2017 16:24:54 +0100
+Subject: [spice-server] stream-device: Limit sending queue from guest to
+ server
+
+Do not allow the guest to fill host memory.
+Also having a huge queue mainly cause to have a higher video
+latency.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 41 ++++++++++++++++++++++++++++++++++++++++-
+ server/stream-channel.h | 10 ++++++++++
+ server/stream-device.c  | 35 ++++++++++++++++++++++++++++++++++-
+ 3 files changed, 84 insertions(+), 2 deletions(-)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index 51b8badf9..ec4bf021d 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -71,9 +71,15 @@ struct StreamChannel {
+     /* size of the current video stream */
+     unsigned width, height;
+ 
++    StreamQueueStat queue_stat;
++
+     /* callback to notify when a stream should be started or stopped */
+     stream_channel_start_proc start_cb;
+     void *start_opaque;
++
++    /* callback to notify when queue statistics changes */
++    stream_channel_queue_stat_proc queue_cb;
++    void *queue_opaque;
+ };
+ 
+ struct StreamChannelClass {
+@@ -98,6 +104,7 @@ typedef struct StreamCreateItem {
+ 
+ typedef struct StreamDataItem {
+     RedPipeItem base;
++    StreamChannel *channel;
+     // NOTE: this must be the last field in the structure
+     SpiceMsgDisplayStreamData data;
+ } StreamDataItem;
+@@ -454,6 +461,27 @@ stream_channel_change_format(StreamChannel *channel, const StreamMsgFormat *fmt)
+     red_channel_pipes_add(red_channel, &item->base);
+ }
+ 
++static inline void
++stream_channel_update_queue_stat(StreamChannel *channel,
++                                 int32_t num_diff, int32_t size_diff)
++{
++    channel->queue_stat.num_items += num_diff;
++    channel->queue_stat.size += size_diff;
++    if (channel->queue_cb) {
++        channel->queue_cb(channel->queue_opaque, &channel->queue_stat, channel);
++    }
++}
++
++static void
++data_item_free(RedPipeItem *base)
++{
++    StreamDataItem *pipe_item = SPICE_UPCAST(StreamDataItem, base);
++
++    stream_channel_update_queue_stat(pipe_item->channel, -1, -pipe_item->data.data_size);
++
++    g_free(pipe_item);
++}
++
+ void
+ stream_channel_send_data(StreamChannel *channel, const void *data, size_t size, uint32_t mm_time)
+ {
+@@ -467,10 +495,13 @@ stream_channel_send_data(StreamChannel *channel, const void *data, size_t size,
+     RedChannel *red_channel = RED_CHANNEL(channel);
+ 
+     StreamDataItem *item = g_malloc(sizeof(*item) + size);
+-    red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_DATA);
++    red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_STREAM_DATA,
++                            data_item_free);
+     item->data.base.id = channel->stream_id;
+     item->data.base.multi_media_time = mm_time;
+     item->data.data_size = size;
++    item->channel = channel;
++    stream_channel_update_queue_stat(channel, 1, size);
+     // TODO try to optimize avoiding the copy
+     memcpy(item->data.data, data, size);
+     red_channel_pipes_add(red_channel, &item->base);
+@@ -485,6 +516,14 @@ stream_channel_register_start_cb(StreamChannel *channel,
+ }
+ 
+ void
++stream_channel_register_queue_stat_cb(StreamChannel *channel,
++                                      stream_channel_queue_stat_proc cb, void *opaque)
++{
++    channel->queue_cb = cb;
++    channel->queue_opaque = opaque;
++}
++
++void
+ stream_channel_reset(StreamChannel *channel)
+ {
+     struct {
+diff --git a/server/stream-channel.h b/server/stream-channel.h
+index bd075a951..f961d7157 100644
+--- a/server/stream-channel.h
++++ b/server/stream-channel.h
+@@ -67,6 +67,16 @@ typedef void (*stream_channel_start_proc)(void *opaque, struct StreamMsgStartSto
+ void stream_channel_register_start_cb(StreamChannel *channel,
+                                       stream_channel_start_proc cb, void *opaque);
+ 
++typedef struct StreamQueueStat {
++    uint32_t num_items;
++    uint32_t size;
++} StreamQueueStat;
++
++typedef void (*stream_channel_queue_stat_proc)(void *opaque, const StreamQueueStat *stats,
++                                               StreamChannel *channel);
++void stream_channel_register_queue_stat_cb(StreamChannel *channel,
++                                           stream_channel_queue_stat_proc cb, void *opaque);
++
+ G_END_DECLS
+ 
+ #endif /* STREAM_CHANNEL_H_ */
+diff --git a/server/stream-device.c b/server/stream-device.c
+index ae108788b..f87538d49 100644
+--- a/server/stream-device.c
++++ b/server/stream-device.c
+@@ -44,6 +44,7 @@ struct StreamDevice {
+     uint8_t hdr_pos;
+     bool has_error;
+     bool opened;
++    bool flow_stopped;
+     StreamChannel *stream_channel;
+ };
+ 
+@@ -72,7 +73,7 @@ stream_device_read_msg_from_dev(RedCharDevice *self, SpiceCharDeviceInstance *si
+     int n;
+     bool handled = false;
+ 
+-    if (dev->has_error || !dev->stream_channel) {
++    if (dev->has_error || dev->flow_stopped || !dev->stream_channel) {
+         return NULL;
+     }
+ 
+@@ -181,6 +182,9 @@ handle_msg_data(StreamDevice *dev, SpiceCharDeviceInstance *sin)
+         if (n <= 0) {
+             break;
+         }
++        // TODO collect all message ??
++        // up: we send a single frame together
++        // down: guest can cause a crash
+         stream_channel_send_data(dev->stream_channel, buf, n, reds_get_mm_time());
+         dev->hdr.size -= n;
+     }
+@@ -233,6 +237,33 @@ stream_device_stream_start(void *opaque, StreamMsgStartStop *start,
+     red_char_device_write_buffer_add(char_dev, buf);
+ }
+ 
++static void
++stream_device_stream_queue_stat(void *opaque, const StreamQueueStat *stats G_GNUC_UNUSED,
++                                StreamChannel *stream_channel G_GNUC_UNUSED)
++{
++    StreamDevice *dev = (StreamDevice *) opaque;
++
++    if (!dev->opened) {
++        return;
++    }
++
++    // very easy control flow... if any data stop
++    // this seems a very small queue but as we use tcp
++    // there's already that queue
++    if (stats->num_items) {
++        dev->flow_stopped = true;
++        return;
++    }
++
++    if (dev->flow_stopped) {
++        dev->flow_stopped = false;
++        // TODO resume flow...
++        // avoid recursion if we need to call get data from data handling from
++        // data handling
++        red_char_device_wakeup(&dev->parent);
++    }
++}
++
+ RedCharDevice *
+ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin)
+ {
+@@ -277,6 +308,7 @@ allocate_channels(StreamDevice *dev)
+     dev->stream_channel = stream_channel;
+ 
+     stream_channel_register_start_cb(stream_channel, stream_device_stream_start, dev);
++    stream_channel_register_queue_stat_cb(stream_channel, stream_device_stream_queue_stat, dev);
+ }
+ 
+ static void
+@@ -303,6 +335,7 @@ stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
+     }
+     dev->hdr_pos = 0;
+     dev->has_error = false;
++    dev->flow_stopped = false;
+     red_char_device_reset(char_dev);
+     reset_channels(dev);
+ }
diff --git a/SOURCES/0020-stream-channel-Activate-streaming-report-from-client.patch b/SOURCES/0020-stream-channel-Activate-streaming-report-from-client.patch
new file mode 100644
index 0000000..859488f
--- /dev/null
+++ b/SOURCES/0020-stream-channel-Activate-streaming-report-from-client.patch
@@ -0,0 +1,65 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Frediano Ziglio <fziglio@redhat.com>
+Date: Wed, 7 Jun 2017 13:13:21 +0100
+Subject: [spice-server] stream-channel: Activate streaming report from client
+
+Setting the capability is not enough, each stream must be enabled
+so do so if client support them.
+
+Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
+Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
+---
+ server/stream-channel.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/server/stream-channel.c b/server/stream-channel.c
+index ec4bf021d..7e15dd363 100644
+--- a/server/stream-channel.c
++++ b/server/stream-channel.c
+@@ -27,6 +27,7 @@
+ #include "reds.h"
+ #include "common-graphics-channel.h"
+ #include "display-limits.h"
++#include "stream.h" // TODO remove, put common stuff
+ 
+ #define TYPE_STREAM_CHANNEL_CLIENT stream_channel_client_get_type()
+ 
+@@ -95,6 +96,7 @@ enum {
+     RED_PIPE_ITEM_TYPE_STREAM_CREATE,
+     RED_PIPE_ITEM_TYPE_STREAM_DATA,
+     RED_PIPE_ITEM_TYPE_STREAM_DESTROY,
++    RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT,
+ };
+ 
+ typedef struct StreamCreateItem {
+@@ -230,6 +232,20 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
+         spice_marshall_msg_display_stream_create(m, &item->stream_create);
+         break;
+     }
++    case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: {
++        if (client->stream_id < 0
++            || !red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_STREAM_REPORT)) {
++            return;
++        }
++        SpiceMsgDisplayStreamActivateReport msg;
++        msg.stream_id = client->stream_id;
++        msg.unique_id = 1; // TODO useful ?
++        msg.max_window_size = RED_STREAM_CLIENT_REPORT_WINDOW;
++        msg.timeout_ms = RED_STREAM_CLIENT_REPORT_TIMEOUT;
++        red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT);
++        spice_marshall_msg_display_stream_activate_report(m, &msg);
++        break;
++    }
+     case RED_PIPE_ITEM_TYPE_STREAM_DATA: {
+         StreamDataItem *item = SPICE_UPCAST(StreamDataItem, pipe_item);
+         red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA);
+@@ -459,6 +475,9 @@ stream_channel_change_format(StreamChannel *channel, const StreamMsgFormat *fmt)
+     item->stream_create.dest = (SpiceRect) { 0, 0, fmt->width, fmt->height };
+     item->stream_create.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
+     red_channel_pipes_add(red_channel, &item->base);
++
++    // activate stream report if possible
++    red_channel_pipes_add_type(red_channel, RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
+ }
+ 
+ static inline void
diff --git a/SPECS/spice.spec b/SPECS/spice.spec
index 92a0fa4..2838eb9 100644
--- a/SPECS/spice.spec
+++ b/SPECS/spice.spec
@@ -1,19 +1,31 @@
 Name:           spice
-Version:        0.12.8
-Release:        2%{?dist}.1
+Version:        0.14.0
+Release:        2%{?dist}
 Summary:        Implements the SPICE protocol
 Group:          User Interface/Desktops
 License:        LGPLv2+
 URL:            http://www.spice-space.org/
 Source0:        http://www.spice-space.org/download/releases/%{name}-%{version}.tar.bz2
-Patch01: 0001-Call-migrate_end_complete-after-falling-back-to-swit.patch
-Patch02: 0002-Prevent-possible-DoS-attempts-during-protocol-handsh.patch
-Patch03: 0003-Prevent-integer-overflows-in-capability-checks.patch
-Patch04: 0004-main-channel-Prevent-overflow-reading-messages-from-.patch
-Patch05: 0005-reds-Check-link-header-magic-without-waiting-for-the.patch
-Patch06: 0006-reds-Disconnect-when-receiving-overly-big-ClientMoni.patch
-Patch07: 0007-reds-Avoid-integer-overflows-handling-monitor-config.patch
-Patch08: 0008-reds-Avoid-buffer-overflows-handling-monitor-configu.patch
+Patch1:         0001-inputs-channel-Check-message-size-handling-migration.patch
+Patch2:         0002-red-channel-Remove-red_channel_init_outgoing_message.patch
+Patch3:         0003-reds-Remove-leak-allocating-migration-state.patch
+Patch4:         0004-tests-Check-leaks-registering-migration-interface.patch
+Patch5:         0005-Notify-client-of-the-creation-of-new-channels-dynami.patch
+Patch6:         0006-stream-device-Add-device-to-handle-streaming.patch
+Patch7:         0007-stream-device-Start-parsing-new-protocol-from-guest.patch
+Patch8:         0008-stream-channel-Write-a-base-channel-to-implement-the.patch
+Patch9:         0009-stream-channel-Start-implementing-DisplayChannel-pro.patch
+Patch10:        0010-stream-device-Create-channel-for-stream-device.patch
+Patch11:        0011-stream-device-Handle-streaming-data-from-device-to-c.patch
+Patch12:        0012-stream-channel-Allows-not-fixed-size.patch
+Patch13:        0013-stream-channel-Allows-to-register-callback-to-get-ne.patch
+Patch14:        0014-stream-channel-Support-client-connection-disconnecti.patch
+Patch15:        0015-stream-channel-Do-not-show-an-empty-blank-screen-on-.patch
+Patch16:        0016-char-device-Do-not-stop-and-clear-interface-on-reset.patch
+Patch17:        0017-stream-device-Start-supporting-resetting-device-when.patch
+Patch18:        0018-stream-device-Create-channel-when-needed.patch
+Patch19:        0019-stream-device-Limit-sending-queue-from-guest-to-serv.patch
+Patch20:        0020-stream-channel-Activate-streaming-report-from-client.patch
 
 # https://bugzilla.redhat.com/show_bug.cgi?id=613529
 %if 0%{?rhel}
@@ -28,8 +40,11 @@ BuildRequires:  spice-protocol >= 0.12.10
 BuildRequires:  celt051-devel
 BuildRequires:  pixman-devel alsa-lib-devel openssl-devel libjpeg-turbo-devel
 BuildRequires:  libcacard-devel cyrus-sasl-devel
+BuildRequires:  lz4-devel
 BuildRequires:  pyparsing
+BuildRequires:  opus-devel
 BuildRequires:  git
+BuildRequires:  autoconf automake libtool
 
 %description
 The Simple Protocol for Independent Computing Environments (SPICE) is
@@ -73,8 +88,8 @@ using spice-server, you will need to install spice-server-devel.
 
 
 %build
-%define configure_client --disable-client
-%configure --enable-smartcard %{configure_client}
+autoreconf -fi
+%configure --enable-smartcard --disable-client
 make %{?_smp_mflags} WARN_CFLAGS='' V=1
 
 
@@ -100,9 +115,25 @@ mkdir -p %{buildroot}%{_libexecdir}
 
 
 %changelog
-* Wed Jul 05 2017 Christophe Fergeau <cfergeau@redhat.com> 0.12.8-2.1
-- Redo build properly versioned as a zstream build
-  Related: CVE-2017-7506
+* Thu Oct 12 2017 Christophe Fergeau <cfergeau@redhat.com> - 0.14.0-2
+- Add streaming patches for use with spice-streaming-agent
+  Related: rhbz#1478356
+
+* Wed Oct 11 2017 Christophe Fergeau <cfergeau@redhat.com> - 0.14.0-1
+- Rebase to 0.14.0 release
+  Resolves: rhbz#1472948
+
+* Fri Sep 22 2017 Christophe Fergeau <cfergeau@redhat.com> 0.13.90-2
+- Add lz4-devel BuildRequires
+  Resolves: rhbz#1460191
+
+* Wed Jul 26 2017 Christophe Fergeau <cfergeau@redhat.com> 0.13.90-1
+- Rebase to latest upstream release
+  Resolves: rhbz#1472948
+
+* Fri Jul 14 2017 Jonathon Jongsma <jjongsma@redhat.com> - 0.12.8-4
+- build with opus support
+  Resolves: rhbz#1456832
 
 * Fri Jun 30 2017 Christophe Fergeau <cfergeau@redhat.com> 0.12.8-3
 - Prevent potential buffer/integer overflows with invalid MonitorsConfig messages