[Spice-commits] client/demarshallers.h client/red_channel.h python_modules/demarshal.py server/demarshallers.h server/reds.c server/red_worker.c server/snd_worker.c

Alexander Larsson alexl at kemper.freedesktop.org
Tue Jun 22 01:54:40 PDT 2010


 client/demarshallers.h      |    4 +++-
 client/red_channel.h        |    9 +++++----
 python_modules/demarshal.py |   25 ++++++++++++++++++-------
 server/demarshallers.h      |    4 +++-
 server/red_worker.c         |    5 +++--
 server/reds.c               |    6 ++++--
 server/snd_worker.c         |    5 +++--
 7 files changed, 39 insertions(+), 19 deletions(-)

New commits:
commit 9123e24e7b68ad36d4ac2b8f325ea249a5ea9ff5
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 10:53:24 2010 +0200

    Add destructor for demarshalled messages
    
    This is required because we don't want to free messages that just
    refer to the unparsed message (like SpiceMsgData).
    
    Also, in the future we might need it for more complex demarshalling.

diff --git a/client/demarshallers.h b/client/demarshallers.h
index 8118973..ab0fc58 100644
--- a/client/demarshallers.h
+++ b/client/demarshallers.h
@@ -17,7 +17,9 @@
 #ifndef _H_DEMARSHAL
 #define _H_DEMARSHAL
 
-typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out);
+typedef void (*message_destructor_t)(uint8_t *message);
+typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor,
+						size_t *size_out, message_destructor_t *free_message);
 
 spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type);
 
diff --git a/client/red_channel.h b/client/red_channel.h
index a9d3ee5..c2528ab 100644
--- a/client/red_channel.h
+++ b/client/red_channel.h
@@ -265,6 +265,7 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
     uint16_t type;
     uint32_t size;
     size_t parsed_size;
+    message_destructor_t parsed_free;
 
     if (message.sub_list()) {
         SpiceSubMessageList *sub_list;
@@ -274,7 +275,7 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
             msg = (uint8_t *)(sub + 1);
             type = sub->type;
             size = sub->size;
-            parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size);
+            parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size, &parsed_free);
 
             if (parsed == NULL) {
                 THROW("failed to parse message type %d", type);
@@ -283,14 +284,14 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
             RedPeer::InMessage sub_message(type, parsed_size, parsed);
             (_obj.*_handlers[type])(&sub_message);
 
-            free(parsed);
+            parsed_free(parsed);
         }
     }
 
     msg = message.data();
     type = message.type();
     size = message.size();
-    parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size);
+    parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size, &parsed_free);
     RedPeer::InMessage main_message(type, parsed_size, parsed);
 
     if (parsed == NULL) {
@@ -298,7 +299,7 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
     }
 
     (_obj.*_handlers[type])(&main_message);
-    free(parsed);
+    parsed_free(parsed);
 }
 
 template <class HandlerClass, unsigned int channel_id>
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 8b90458..b1c4135 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -41,9 +41,10 @@ def write_parser_helpers(writer):
 
     writer.newline()
     writer.statement("typedef struct PointerInfo PointerInfo")
+    writer.statement("typedef void (*message_destructor_t)(uint8_t *message)");
     writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)")
-    writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out)")
-    writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out)")
+    writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out, message_destructor_t *free_message)")
+    writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message)")
 
     writer.newline()
     writer.begin_block("struct PointerInfo")
@@ -820,6 +821,13 @@ def write_ptr_info_check(writer):
                 writer.error_check("end == NULL")
     writer.newline()
 
+def write_nofree(writer):
+    if writer.is_generated("helper", "nofree"):
+        return
+    writer = writer.function_helper()
+    scope = writer.function("nofree", "static void", "uint8_t *data")
+    writer.end_block()
+
 def write_msg_parser(writer, message):
     msg_name = message.c_name()
     function_name = "parse_%s" % msg_name
@@ -833,7 +841,7 @@ def write_msg_parser(writer, message):
     writer.newline()
     parent_scope = writer.function(function_name,
                                    "uint8_t *",
-                                   "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size", True)
+                                   "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size, message_destructor_t *free_message", True)
     parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos");
     parent_scope.variable_def("uint8_t *", "start = message_start");
     parent_scope.variable_def("uint8_t *", "data = NULL");
@@ -860,8 +868,10 @@ def write_msg_parser(writer, message):
     writer.newline().comment("Validated extents and calculated size").newline()
 
     if message.has_attr("nocopy"):
+        write_nofree(writer)
         writer.assign("data", "message_start")
         writer.assign("*size", "message_end - message_start")
+        writer.assign("*free_message", "nofree")
     else:
         writer.assign("data", "(uint8_t *)malloc(mem_size)")
         writer.error_check("data == NULL")
@@ -882,6 +892,7 @@ def write_msg_parser(writer, message):
 
         writer.newline()
         writer.assign("*size", "end - data")
+        writer.assign("*free_message", "(message_destructor_t) free")
 
     writer.statement("return data")
     writer.newline()
@@ -922,7 +933,7 @@ def write_channel_parser(writer, channel, server):
     writer.newline()
     scope = writer.function(function_name,
                             "uint8_t *",
-                            "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out")
+                            "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message")
 
     helpers = writer.function_helper()
 
@@ -944,7 +955,7 @@ def write_channel_parser(writer, channel, server):
     for r in ranges:
         d = d + 1
         with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False):
-            writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out)" % (d, r[0]))
+            writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out, free_message)" % (d, r[0]))
     writer.newline()
 
     writer.statement("return NULL")
@@ -1006,7 +1017,7 @@ def write_full_protocol_parser(writer, is_server):
         function_name = "spice_parse_reply"
     scope = writer.function(function_name,
                             "uint8_t *",
-                            "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out")
+                            "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message")
     scope.variable_def("spice_parse_channel_func_t", "func" )
 
     if is_server:
@@ -1015,7 +1026,7 @@ def write_full_protocol_parser(writer, is_server):
         writer.assign("func", "spice_get_client_channel_parser(channel, NULL)")
 
     with writer.if_block("func != NULL"):
-        writer.statement("return func(message_start, message_end, message_type, minor, size_out)")
+        writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)")
 
     writer.statement("return NULL")
     writer.end_block()
diff --git a/server/demarshallers.h b/server/demarshallers.h
index e568cd0..abe9dfa 100644
--- a/server/demarshallers.h
+++ b/server/demarshallers.h
@@ -17,7 +17,9 @@
 #ifndef _H_DEMARSHAL
 #define _H_DEMARSHAL
 
-typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out);
+typedef void (*message_destructor_t)(uint8_t *message);
+typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor,
+						size_t *size_out, message_destructor_t *free_message);
 
 spice_parse_channel_func_t spice_get_client_channel_parser(uint32_t channel, unsigned int *max_message_type);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 3a0b16e..ee37222 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -10459,6 +10459,7 @@ static void red_receive(RedChannel *channel)
                 uint8_t *data = (uint8_t *)(header+1);
                 size_t parsed_size;
                 uint8_t *parsed;
+                message_destructor_t parsed_free;
 
                 n = channel->recive_data.now - (uint8_t *)header;
                 if (n < sizeof(SpiceDataHeader) ||
@@ -10466,7 +10467,7 @@ static void red_receive(RedChannel *channel)
                     break;
                 }
                 parsed = channel->parser((void *)data, data + header->size, header->type,
-                                         SPICE_VERSION_MINOR, &parsed_size);
+                                         SPICE_VERSION_MINOR, &parsed_size, &parsed_free);
 
                 if (parsed == NULL) {
                     red_printf("failed to parse message type %d", header->type);
@@ -10479,7 +10480,7 @@ static void red_receive(RedChannel *channel)
                     channel->disconnect(channel);
                     return;
                 }
-                free(parsed);
+                parsed_free(parsed);
                 channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)header +
                                                                    sizeof(SpiceDataHeader) +
                                                                    header->size);
diff --git a/server/reds.c b/server/reds.c
index f9d91db..8c16896 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -797,16 +797,18 @@ static int handle_incoming(RedsStreamContext *peer, IncomingHandler *handler)
                 uint8_t *data = (uint8_t *)(header+1);
                 size_t parsed_size;
                 uint8_t *parsed;
+                message_destructor_t parsed_free;
+
 
                 buf += sizeof(SpiceDataHeader) + header->size;
                 parsed = handler->parser(data, data + header->size, header->type,
-                                         SPICE_VERSION_MINOR, &parsed_size);
+                                         SPICE_VERSION_MINOR, &parsed_size, &parsed_free);
                 if (parsed == NULL) {
                     red_printf("failed to parse message type %d", header->type);
                     return -1;
                 }
                 handler->handle_message(handler->opaque, parsed_size, header->type, parsed);
-                free(parsed);
+                parsed_free(parsed);
                 if (handler->shut) {
                     return -1;
                 }
diff --git a/server/snd_worker.c b/server/snd_worker.c
index d55380c..6c0f9d6 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -415,13 +415,14 @@ static void snd_receive(void* data)
                 uint8_t *data = (uint8_t *)(header+1);
                 size_t parsed_size;
                 uint8_t *parsed;
+                message_destructor_t parsed_free;
 
                 n = channel->recive_data.now - (uint8_t *)header;
                 if (n < sizeof(SpiceDataHeader) || n < sizeof(SpiceDataHeader) + header->size) {
                     break;
                 }
                 parsed = channel->parser((void *)data, data + header->size, header->type,
-                                         SPICE_VERSION_MINOR, &parsed_size);
+                                         SPICE_VERSION_MINOR, &parsed_size, &parsed_free);
                 if (parsed == NULL) {
                     red_printf("failed to parse message type %d", header->type);
                     snd_disconnect_channel(channel);
@@ -432,7 +433,7 @@ static void snd_receive(void* data)
                     snd_disconnect_channel(channel);
                     return;
                 }
-                free(parsed);
+                parsed_free(parsed);
                 channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)header +
                                                                  sizeof(SpiceDataHeader) +
                                                                  header->size);


More information about the Spice-commits mailing list