[spice PATCH 14/55] red_channel: handle sending SPICE_MSG_MIGRATE

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The relevant code is common to all channels.

The patch also contains a fix to the return value for
handle_migrate_data callback: s/uint64_t/int
---
 server/inputs_channel.c |    3 ++-
 server/main_channel.c   |    5 +++--
 server/red_channel.c    |   38 ++++++++++++++++++++++++++++++++++----
 server/red_channel.h    |   14 +++++++++++---
 server/red_worker.c     |   23 ++++++++++++++---------
 server/smartcard.c      |    4 +++-
 server/spicevmc.c       |    3 ++-
 7 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/server/inputs_channel.c b/server/inputs_channel.c
index e14e995..269e2dc 100644
--- a/server/inputs_channel.c
+++ b/server/inputs_channel.c
@@ -551,7 +551,8 @@ void inputs_init(void)
                                     FALSE, /* handle_acks */
                                     spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL),
                                     inputs_channel_handle_parsed,
-                                    &channel_cbs);
+                                    &channel_cbs,
+                                    0);
 
     if (!g_inputs_channel) {
         spice_error("failed to allocate Inputs Channel");
diff --git a/server/main_channel.c b/server/main_channel.c
index 6123068..6398965 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -475,7 +475,7 @@ static uint64_t main_channel_handle_migrate_data_get_serial(RedChannelClient *ba
     return data->serial;
 }
 
-static uint64_t main_channel_handle_migrate_data(RedChannelClient *base,
+static int main_channel_handle_migrate_data(RedChannelClient *base,
     uint32_t size, void *message)
 {
     MainChannelClient *mcc = SPICE_CONTAINEROF(base, MainChannelClient, base);
@@ -1138,7 +1138,8 @@ MainChannel* main_channel_init(void)
                                         FALSE, FALSE, /* handle_acks */
                                         spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL),
                                         main_channel_handle_parsed,
-                                        &channel_cbs);
+                                        &channel_cbs,
+                                        SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER);
     spice_assert(channel);
     red_channel_set_cap(channel, SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
 
diff --git a/server/red_channel.c b/server/red_channel.c
index a108bc2..d715ce8 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -452,6 +452,20 @@ static void red_channel_client_send_set_ack(RedChannelClient *rcc)
     red_channel_client_begin_send_message(rcc);
 }
 
+static void red_channel_client_send_migrate(RedChannelClient *rcc)
+{
+    SpiceMsgMigrate migrate;
+
+    red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, NULL);
+    migrate.flags = rcc->channel->migration_flags;
+    spice_marshall_msg_migrate(rcc->send_data.marshaller, &migrate);
+    if (rcc->channel->migration_flags & SPICE_MIGRATE_NEED_FLUSH) {
+        rcc->wait_migrate_flush_mark = TRUE;
+    }
+
+    red_channel_client_begin_send_message(rcc);
+}
+
 static void red_channel_client_send_item(RedChannelClient *rcc, PipeItem *item)
 {
     int handled = TRUE;
@@ -463,6 +477,10 @@ static void red_channel_client_send_item(RedChannelClient *rcc, PipeItem *item)
             red_channel_client_send_set_ack(rcc);
             free(item);
             break;
+        case PIPE_ITEM_TYPE_MIGRATE:
+            red_channel_client_send_migrate(rcc);
+            free(item);
+            break;
         default:
             handled = FALSE;
     }
@@ -684,8 +702,9 @@ static void red_channel_client_default_disconnect(RedChannelClient *base)
     red_channel_client_disconnect(base);
 }
 
-static void red_channel_client_default_migrate(RedChannelClient *base)
+void red_channel_client_default_migrate(RedChannelClient *rcc)
 {
+    red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_MIGRATE);
 }
 
 RedChannel *red_channel_create(int size,
@@ -693,7 +712,8 @@ RedChannel *red_channel_create(int size,
                                uint32_t type, uint32_t id,
                                int migrate, int handle_acks,
                                channel_handle_message_proc handle_message,
-                               ChannelCbs *channel_cbs)
+                               ChannelCbs *channel_cbs,
+                               uint32_t migration_flags)
 {
     RedChannel *channel;
     ClientCbs client_cbs = { NULL, };
@@ -701,11 +721,14 @@ RedChannel *red_channel_create(int size,
     spice_assert(size >= sizeof(*channel));
     spice_assert(channel_cbs->config_socket && channel_cbs->on_disconnect && handle_message &&
            channel_cbs->alloc_recv_buf && channel_cbs->release_item);
+    spice_assert(channel_cbs->handle_migrate_data ||
+                 !(migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER));
     channel = spice_malloc0(size);
     channel->type = type;
     channel->id = id;
     channel->refs = 1;
     channel->handle_acks = handle_acks;
+    channel->migration_flags = migration_flags;
     memcpy(&channel->channel_cbs, channel_cbs, sizeof(ChannelCbs));
 
     channel->core = core;
@@ -801,12 +824,14 @@ RedChannel *red_channel_create_parser(int size,
                                int migrate, int handle_acks,
                                spice_parse_channel_func_t parser,
                                channel_handle_parsed_proc handle_parsed,
-                               ChannelCbs *channel_cbs)
+                               ChannelCbs *channel_cbs,
+                               uint32_t migration_flags)
 {
     RedChannel *channel = red_channel_create(size, core, type, id,
                                              migrate, handle_acks,
                                              do_nothing_handle_message,
-                                             channel_cbs);
+                                             channel_cbs,
+                                             migration_flags);
 
     if (channel == NULL) {
         return NULL;
@@ -1089,7 +1114,12 @@ int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
     case SPICE_MSGC_DISCONNECTING:
         break;
     case SPICE_MSGC_MIGRATE_FLUSH_MARK:
+        if (!rcc->wait_migrate_flush_mark) {
+            spice_error("unexpected flush mark");
+            return FALSE;
+        }
         red_channel_handle_migrate_flush_mark(rcc);
+        rcc->wait_migrate_flush_mark = FALSE;
         break;
     case SPICE_MSGC_MIGRATE_DATA:
         red_channel_handle_migrate_data(rcc, size, message);
diff --git a/server/red_channel.h b/server/red_channel.h
index acb49cd..35d11a6 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -142,6 +142,8 @@ typedef struct MainChannelClient MainChannelClient;
  * */
 enum {
     PIPE_ITEM_TYPE_SET_ACK=1,
+    PIPE_ITEM_TYPE_MIGRATE,
+
     PIPE_ITEM_TYPE_CHANNEL_BASE=101,
 };
 
@@ -168,7 +170,7 @@ typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc);
 typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc);
 
 typedef int (*channel_handle_migrate_flush_mark_proc)(RedChannelClient *base);
-typedef uint64_t (*channel_handle_migrate_data_proc)(RedChannelClient *base,
+typedef int (*channel_handle_migrate_data_proc)(RedChannelClient *base,
                                                 uint32_t size, void *message);
 typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient *base,
                                             uint32_t size, void *message);
@@ -265,6 +267,7 @@ struct RedChannelClient {
     RedChannelCapabilities remote_caps;
     int is_mini_header;
     int destroying;
+    int wait_migrate_flush_mark;
 };
 
 struct RedChannel {
@@ -296,6 +299,7 @@ struct RedChannel {
     ClientCbs client_cbs;
 
     RedChannelCapabilities local_caps;
+    uint32_t migration_flags;
 
     void *data;
 
@@ -313,7 +317,8 @@ RedChannel *red_channel_create(int size,
                                uint32_t type, uint32_t id,
                                int migrate, int handle_acks,
                                channel_handle_message_proc handle_message,
-                               ChannelCbs *channel_cbs);
+                               ChannelCbs *channel_cbs,
+                               uint32_t migration_flags);
 
 /* alternative constructor, meant for marshaller based (inputs,main) channels,
  * will become default eventually */
@@ -323,7 +328,8 @@ RedChannel *red_channel_create_parser(int size,
                                int migrate, int handle_acks,
                                spice_parse_channel_func_t parser,
                                channel_handle_parsed_proc handle_parsed,
-                               ChannelCbs *channel_cbs);
+                               ChannelCbs *channel_cbs,
+                               uint32_t migration_flags);
 
 void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs);
 // caps are freed when the channel is destroyed
@@ -350,6 +356,8 @@ void red_channel_client_destroy_dummy(RedChannelClient *rcc);
 int red_channel_is_connected(RedChannel *channel);
 int red_channel_client_is_connected(RedChannelClient *rcc);
 
+void red_channel_client_default_migrate(RedChannelClient *rcc);
+
 /*
  * the disconnect callback is called from the channel's thread,
  * i.e., for display channels - red worker thread, for all the other - from the main thread.
diff --git a/server/red_worker.c b/server/red_worker.c
index 9330fff..7c71ba0 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -253,7 +253,8 @@ enum {
     PIPE_ITEM_TYPE_DRAW = PIPE_ITEM_TYPE_CHANNEL_BASE,
     PIPE_ITEM_TYPE_INVAL_ONE,
     PIPE_ITEM_TYPE_CURSOR,
-    PIPE_ITEM_TYPE_MIGRATE,
+    PIPE_ITEM_TYPE_DISPLAY_MIGRATE, /* tmp. It will be substituted with
+                                       red_channel/PIPE_ITEM_TYPE_MIGRATE */
     PIPE_ITEM_TYPE_CURSOR_INIT,
     PIPE_ITEM_TYPE_IMAGE,
     PIPE_ITEM_TYPE_STREAM_CREATE,
@@ -8798,7 +8799,7 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item
     case PIPE_ITEM_TYPE_VERB:
         red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb);
         break;
-    case PIPE_ITEM_TYPE_MIGRATE:
+    case PIPE_ITEM_TYPE_DISPLAY_MIGRATE:
         spice_info("PIPE_ITEM_TYPE_MIGRATE");
         display_channel_marshall_migrate(rcc, m);
         break;
@@ -8863,7 +8864,7 @@ static void cursor_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item)
     case PIPE_ITEM_TYPE_VERB:
         red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb);
         break;
-    case PIPE_ITEM_TYPE_MIGRATE:
+    case PIPE_ITEM_TYPE_DISPLAY_MIGRATE:
         spice_info("PIPE_ITEM_TYPE_MIGRATE");
         cursor_channel_marshall_migrate(rcc, m);
         break;
@@ -9011,7 +9012,7 @@ static void red_migrate_display(RedWorker *worker, RedChannelClient *rcc)
     // TODO: replace all worker->display_channel tests with
     // is_connected
     if (red_channel_client_is_connected(rcc)) {
-        red_pipe_add_verb(rcc, PIPE_ITEM_TYPE_MIGRATE);
+        red_pipe_add_verb(rcc, PIPE_ITEM_TYPE_DISPLAY_MIGRATE);
 //        red_pipes_add_verb(&worker->display_channel->common.base,
 //                           SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL);
 //        red_channel_pipes_add_type(&worker->display_channel->common.base,
@@ -9656,7 +9657,7 @@ static uint64_t display_channel_handle_migrate_data_get_serial(
     return migrate_data->message_serial;
 }
 
-static uint64_t display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size,
+static int display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size,
                                                     void *message)
 {
     DisplayChannelMigrateData *migrate_data;
@@ -9905,6 +9906,7 @@ CursorChannelClient *cursor_channel_create_rcc(CommonChannel *common,
 }
 
 static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_type, int migrate,
+                                 int migration_flags,
                                  channel_disconnect_proc on_disconnect,
                                  channel_send_pipe_item_proc send_item,
                                  channel_hold_pipe_item_proc hold_item,
@@ -9935,7 +9937,8 @@ static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_t
                                         TRUE /* handle_acks */,
                                         spice_get_client_channel_parser(channel_type, NULL),
                                         handle_parsed,
-                                        &channel_cbs);
+                                        &channel_cbs,
+                                        migration_flags);
     common = (CommonChannel *)channel;
     if (!channel) {
         goto error;
@@ -10056,7 +10059,7 @@ static void display_channel_client_release_item_before_push(DisplayChannelClient
     }
     case PIPE_ITEM_TYPE_INVAL_ONE:
     case PIPE_ITEM_TYPE_VERB:
-    case PIPE_ITEM_TYPE_MIGRATE:
+    case PIPE_ITEM_TYPE_DISPLAY_MIGRATE:
     case PIPE_ITEM_TYPE_MIGRATE_DATA:
     case PIPE_ITEM_TYPE_PIXMAP_SYNC:
     case PIPE_ITEM_TYPE_PIXMAP_RESET:
@@ -10093,6 +10096,7 @@ static void display_channel_create(RedWorker *worker, int migrate)
     if (!(worker->display_channel = (DisplayChannel *)__new_channel(
             worker, sizeof(*display_channel),
             SPICE_CHANNEL_DISPLAY, migrate,
+            SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER,
             display_channel_client_on_disconnect,
             display_channel_send_item,
             display_channel_hold_pipe_item,
@@ -10213,7 +10217,7 @@ static void red_migrate_cursor(RedWorker *worker, RedChannelClient *rcc)
         red_channel_client_pipe_add_type(rcc,
                                          PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE);
         red_channel_client_pipe_add_type(rcc,
-                                         PIPE_ITEM_TYPE_MIGRATE);
+                                         PIPE_ITEM_TYPE_DISPLAY_MIGRATE);
     }
 }
 
@@ -10252,7 +10256,7 @@ static void cursor_channel_client_release_item_before_push(CursorChannelClient *
     }
     case PIPE_ITEM_TYPE_INVAL_ONE:
     case PIPE_ITEM_TYPE_VERB:
-    case PIPE_ITEM_TYPE_MIGRATE:
+    case PIPE_ITEM_TYPE_DISPLAY_MIGRATE:
     case PIPE_ITEM_TYPE_CURSOR_INIT:
     case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
         free(item);
@@ -10299,6 +10303,7 @@ static void cursor_channel_create(RedWorker *worker, int migrate)
     worker->cursor_channel = (CursorChannel *)__new_channel(
         worker, sizeof(*worker->cursor_channel),
         SPICE_CHANNEL_CURSOR, migrate,
+        0,
         cursor_channel_client_on_disconnect,
         cursor_channel_send_item,
         cursor_channel_hold_pipe_item,
diff --git a/server/smartcard.c b/server/smartcard.c
index 7ec44cb..2ed0bde 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -679,6 +679,7 @@ static void smartcard_init(void)
 {
     ChannelCbs channel_cbs = { NULL, };
     ClientCbs client_cbs = { NULL, };
+    uint32_t migration_flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
 
     spice_assert(!g_smartcard_channel);
 
@@ -695,7 +696,8 @@ static void smartcard_init(void)
                                              FALSE /* migration - TODO?*/,
                                              FALSE /* handle_acks */,
                                              smartcard_channel_handle_message,
-                                             &channel_cbs);
+                                             &channel_cbs,
+                                             migration_flags);
 
     if (!g_smartcard_channel) {
         spice_error("failed to allocate Smartcard Channel");
diff --git a/server/spicevmc.c b/server/spicevmc.c
index b96bf9f..36d901f 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -343,7 +343,8 @@ SpiceCharDeviceState *spicevmc_device_connect(SpiceCharDeviceInstance *sin,
                                    FALSE /* migration - TODO? */,
                                    FALSE /* handle_acks */,
                                    spicevmc_red_channel_client_handle_message,
-                                   &channel_cbs);
+                                   &channel_cbs,
+                                   SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER);
     red_channel_init_outgoing_messages_window(&state->channel);
 
     client_cbs.connect = spicevmc_connect;
-- 
1.7.7.6

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]