summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/demarshallers.h4
-rw-r--r--client/red_channel.h9
-rw-r--r--python_modules/demarshal.py25
-rw-r--r--server/demarshallers.h4
-rw-r--r--server/red_worker.c5
-rw-r--r--server/reds.c6
-rw-r--r--server/snd_worker.c5
7 files changed, 39 insertions, 19 deletions
diff --git a/client/demarshallers.h b/client/demarshallers.h
index 81189735..ab0fc58c 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 a9d3ee54..c2528abe 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 8b90458c..b1c41354 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 e568cd0d..abe9dfab 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 3a0b16e0..ee372220 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 f9d91dbc..8c16896e 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 d55380c8..6c0f9d68 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);