[Spice-commits] 3 commits - server/char_device.c server/char_device.h server/reds.c spice-common

Hans de Goede jwrdegoede at kemper.freedesktop.org
Thu Mar 7 02:49:23 PST 2013


 server/char_device.c |   41 ++++++++++++++++++++++++++---------------
 server/char_device.h |    3 +++
 server/reds.c        |   24 +++++++++++++++++++++++-
 spice-common         |    2 +-
 4 files changed, 53 insertions(+), 17 deletions(-)

New commits:
commit 89d2a68cb7bfa105d27d12497a1f4e340171b525
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 6 13:08:15 2013 +0100

    server/reds: Send the agent a CLIENT_DISCONNECTED msg on client disconnect
    
    Client -> agent messages can spawn multiple VDIChunks. When this happens
    the agent re-assembles the chunks into a complete VDAgentMessage before
    processing it. The server only guarentees coherency at the chunk level,
    so it is not possible for a partial chunk to get delivered to the agent.
    
    But it is possible for some chunks of a VDAgentMessage to be delivered to
    the agent followed by a client to disconnect without the rest of the
    VDAgentMessage being delivered!
    
    This will leave the agent in a wrong state, and the first messages send to it
    by the next client to connect will get seen as the rest of the VDAgentMessage
    from the previous client.
    
    This patch sends the agent a new VD_AGENT_CLIENT_DISCONNECTED message from the
    VDP_SERVER_PORT, on which the agent can then reset its VDP_CLIENT_PORT state.
    
    Note that no capability check is done for this, since the capabilities are
    something negotiated between client and agent. The server will simply always
    send this message on client disconnect, relying on older agents discarding the
    message since it has an unknown type (which both the windows and linux agents
    already do).
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/server/reds.c b/server/reds.c
index ec80e9e..5c46909 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -563,7 +563,29 @@ void reds_client_disconnect(RedClient *client)
    // TODO: we need to handle agent properly for all clients!!!! (e.g., cut and paste, how? Maybe throw away messages
    // if we are in the middle of one from another client)
     if (reds->num_clients == 0) {
-       /* Reset write filter to start with clean state on client reconnect */
+        /* Let the agent know the client is disconnected */
+        if (reds->agent_state.base) {
+            SpiceCharDeviceWriteBuffer *char_dev_buf;
+            VDInternalBuf *internal_buf;
+            uint32_t total_msg_size;
+
+            total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage);
+            char_dev_buf = spice_char_device_write_buffer_get_server_no_token(
+                               reds->agent_state.base, total_msg_size);
+            char_dev_buf->buf_used = total_msg_size;
+            internal_buf = (VDInternalBuf *)char_dev_buf->buf;
+            internal_buf->chunk_header.port = VDP_SERVER_PORT;
+            internal_buf->chunk_header.size = sizeof(VDAgentMessage);
+            internal_buf->header.protocol = VD_AGENT_PROTOCOL;
+            internal_buf->header.type = VD_AGENT_CLIENT_DISCONNECTED;
+            internal_buf->header.opaque = 0;
+            internal_buf->header.size = 0;
+
+            spice_char_device_write_buffer_add(reds->agent_state.base,
+                                               char_dev_buf);
+        }
+
+        /* Reset write filter to start with clean state on client reconnect */
         agent_msg_filter_init(&reds->agent_state.write_filter, agent_copypaste,
                               TRUE);
 
commit 4476c99452202045ca5f1efb79a3c2957fa9bc4b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Mar 6 12:51:43 2013 +0100

    char_device: Add spice_char_device_write_buffer_get_server_no_token()
    
    To allow the server to send agent messages without needing to wait for a
    self-token. IE for sending VD_AGENT_CLIENT_DISCONNECTED messages.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/server/char_device.c b/server/char_device.c
index 49c5dc0..e07eda1 100644
--- a/server/char_device.c
+++ b/server/char_device.c
@@ -72,6 +72,7 @@ enum {
     WRITE_BUFFER_ORIGIN_NONE,
     WRITE_BUFFER_ORIGIN_CLIENT,
     WRITE_BUFFER_ORIGIN_SERVER,
+    WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN,
 };
 
 /* Holding references for avoiding access violation if the char device was
@@ -488,15 +489,14 @@ static void spice_char_dev_write_retry(void *opaque)
     spice_char_device_write_to_device(dev);
 }
 
-static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(SpiceCharDeviceState *dev,
-                                                                        RedClient *client,
-                                                                        int size,
-                                                                        int migrated_data_tokens)
+static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(
+    SpiceCharDeviceState *dev, RedClient *client,
+    int size, int origin, int migrated_data_tokens)
 {
     RingItem *item;
     SpiceCharDeviceWriteBuffer *ret;
 
-    if (!client && !dev->num_self_tokens) {
+    if (origin == WRITE_BUFFER_ORIGIN_SERVER && !dev->num_self_tokens) {
         return NULL;
     }
 
@@ -513,8 +513,10 @@ static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(SpiceCha
         ret->buf = spice_realloc(ret->buf, size);
         ret->buf_size = size;
     }
+    ret->origin = origin;
 
-    if (client) {
+    if (origin == WRITE_BUFFER_ORIGIN_CLIENT) {
+       spice_assert(client);
        SpiceCharDeviceClientState *dev_client = spice_char_device_client_find(dev, client);
        if (dev_client) {
             if (!migrated_data_tokens &&
@@ -523,7 +525,6 @@ static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(SpiceCha
                 spice_char_device_handle_client_overflow(dev_client);
                 goto error;
             }
-            ret->origin = WRITE_BUFFER_ORIGIN_CLIENT;
             ret->client = client;
             if (!migrated_data_tokens && dev_client->do_flow_control) {
                 dev_client->num_client_tokens--;
@@ -534,8 +535,7 @@ static SpiceCharDeviceWriteBuffer *__spice_char_device_write_buffer_get(SpiceCha
             spice_printerr("client not found: dev %p client %p", dev, client);
             goto error;
         }
-    } else {
-        ret->origin = WRITE_BUFFER_ORIGIN_SERVER;
+    } else if (origin == WRITE_BUFFER_ORIGIN_SERVER) {
         dev->num_self_tokens--;
     }
 
@@ -551,7 +551,16 @@ SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_get(SpiceCharDeviceSt
                                                                RedClient *client,
                                                                int size)
 {
-   return  __spice_char_device_write_buffer_get(dev, client, size, 0);
+   return  __spice_char_device_write_buffer_get(dev, client, size, 
+             client ? WRITE_BUFFER_ORIGIN_CLIENT : WRITE_BUFFER_ORIGIN_SERVER,
+             0);
+}
+
+SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_get_server_no_token(
+    SpiceCharDeviceState *dev, int size)
+{
+   return  __spice_char_device_write_buffer_get(dev, NULL, size, 
+             WRITE_BUFFER_ORIGIN_SERVER_NO_TOKEN, 0);
 }
 
 static SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_ref(SpiceCharDeviceWriteBuffer *write_buf)
@@ -945,12 +954,14 @@ int spice_char_device_state_restore(SpiceCharDeviceState *dev,
 
     if (mig_data->write_size > 0) {
         if (mig_data->write_num_client_tokens) {
-            dev->cur_write_buf = __spice_char_device_write_buffer_get(dev, client_state->client,
-                                                                      mig_data->write_size,
-                                                                      mig_data->write_num_client_tokens);
+            dev->cur_write_buf =
+                __spice_char_device_write_buffer_get(dev, client_state->client,
+                    mig_data->write_size, WRITE_BUFFER_ORIGIN_CLIENT,
+                    mig_data->write_num_client_tokens);
         } else {
-            dev->cur_write_buf = __spice_char_device_write_buffer_get(dev, NULL, mig_data->write_size,
-                                                                      0);
+            dev->cur_write_buf =
+                __spice_char_device_write_buffer_get(dev, NULL,
+                    mig_data->write_size, WRITE_BUFFER_ORIGIN_SERVER, 0);
         }
         /* the first write buffer contains all the data that was saved for migration */
         memcpy(dev->cur_write_buf->buf,
diff --git a/server/char_device.h b/server/char_device.h
index 8bfe4ec..99bdb2e 100644
--- a/server/char_device.h
+++ b/server/char_device.h
@@ -181,6 +181,9 @@ void spice_char_device_send_to_client_tokens_set(SpiceCharDeviceState *dev,
 
 SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_get(SpiceCharDeviceState *dev,
                                                                RedClient *client, int size);
+SpiceCharDeviceWriteBuffer *spice_char_device_write_buffer_get_server_no_token(
+    SpiceCharDeviceState *dev, int size);
+
 /* Either add the buffer to the write queue or release it */
 void spice_char_device_write_buffer_add(SpiceCharDeviceState *dev,
                                         SpiceCharDeviceWriteBuffer *write_buf);
commit e67e47fb330a2bc2abf415f59ad90ed5e67db303
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 7 11:52:05 2013 +0100

    Update spice-common
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/spice-common b/spice-common
index b46d36b..063f4dd 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit b46d36bc1c01ca17a64262e157022fd21ad1e795
+Subproject commit 063f4dd3855048bf26e5a9e12f7d10959f4b7489


More information about the Spice-commits mailing list