[Spice-devel] [PATCH 14/33] Generate scheleton for messages and channels

Frediano Ziglio fziglio at redhat.com
Wed Jul 1 10:10:06 PDT 2015


Messages are not generated as stub.
Code partially from demarshaller.

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 python_modules/dissector.py | 138 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 137 insertions(+), 1 deletion(-)

diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index 67d0fa7..9971140 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -1,4 +1,5 @@
 
+from . import ptypes
 from . import codegen
 
 import types
@@ -53,6 +54,124 @@ def write_parser_helpers(writer):
     writer.writeln('#endif')
     writer.newline()
 
+def write_msg_parser(writer, message, server):
+    msg_name = message.c_name()
+    function_name = "dissect_spice_%s_%s" % ('server' if server else 'client', msg_name)
+    if writer.is_generated("msg_parser", function_name):
+        return function_name
+    writer.set_is_generated("msg_parser", function_name)
+
+    msg_type = message.c_type()
+    msg_sizeof = message.sizeof()
+
+    writer.newline()
+    writer.ifdef(message)
+    parent_scope = writer.function(function_name,
+                                   "guint32",
+                                   "GlobalInfo *glb _U_, proto_tree *tree0 _U_, guint32 offset", True)
+
+    writer.statement("return offset")
+    writer.end_block()
+
+    writer.endif(message)
+
+    return function_name
+
+def write_channel_parser(writer, channel, server):
+    writer.newline()
+    ids = {}
+    if server:
+        messages = channel.server_messages
+    else:
+        messages = channel.client_messages
+    for m in messages:
+        ids[m.value] = m
+
+    ranges = []
+    ids2 = ids.copy()
+    while len(ids2) > 0:
+        end = start = min(ids2.keys())
+        while end in ids2:
+            del ids2[end]
+            end = end + 1
+
+        ranges.append( (start, end) )
+
+    if server:
+        function_name = "dissect_spice_data_server_%s" % channel.name
+    else:
+        function_name = "dissect_spice_data_client_%s" % channel.name
+    writer.newline()
+    writer.ifdef(channel)
+    scope = writer.function(function_name,
+                            "guint32",
+                            "guint16 message_type, GlobalInfo *glb _U_, proto_tree *tree _U_, guint32 offset", True)
+
+    helpers = writer.function_helper()
+
+    d = 0
+    for r in ranges:
+        d = d + 1
+        writer.write("static const parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]))
+        writer.begin_block()
+        for i in range(r[0], r[1]):
+            func = write_msg_parser(helpers, ids[i].message_type, server)
+            writer.write(func)
+            if i != r[1] -1:
+                writer.write(",")
+            writer.newline()
+
+        writer.end_block(semicolon = True)
+
+    d = 0
+    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](glb, tree, offset)" % (d, r[0]))
+    writer.newline()
+
+    writer.statement('expert_add_info_format(glb->pinfo, glb->msgtype_item, &ei_spice_unknown_message, "Unknown display server message - cannot dissect")')
+    writer.statement("return offset")
+    writer.end_block()
+    writer.endif(channel)
+
+    return function_name
+
+def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
+    writer.newline()
+    function_name = "spice_%s%s_channel_get_dissect" % ('server' if is_server else 'client', writer.public_prefix)
+
+    writer.function(function_name, "spice_dissect_func_t", "guint8 channel")
+
+    writer.write("static const spice_dissect_func_t channels[%d] = " % (max_channel+1))
+    writer.begin_block()
+    channel = None
+    for i in range(0, max_channel + 1):
+        if i in channel_parsers:
+            channel = channel_parsers[i][0]
+            writer.ifdef(channel)
+            writer.write(channel_parsers[i][1])
+        else:
+            writer.write("NULL")
+
+        if i != max_channel:
+            writer.write(",")
+        writer.newline()
+        if channel and channel.has_attr("ifdef"):
+            writer.ifdef_else(channel)
+            writer.write("NULL")
+            if i != max_channel:
+                writer.write(",")
+            writer.newline()
+            writer.endif(channel)
+    writer.end_block(semicolon = True)
+
+    with writer.if_block("channel < %d" % (max_channel + 1)):
+        writer.statement("return channels[channel]")
+
+    writer.statement("return NULL")
+    writer.end_block()
+
 
 def write_protocol_definitions(writer):
     global hf_defs
@@ -114,8 +233,25 @@ def write_protocol_parser(writer, proto):
         writer.newline()
     hf_writer = writer.get_subwriter()
 
+    # put everything else after
+    defs_writer = writer
+    writer = writer.get_subwriter()
+
     # put fields definition at last
-    write_protocol_definitions(writer)
+    write_protocol_definitions(defs_writer)
+
+    # scan all, looks for items and tree
+    # list add items and tree
+    # write all structure functions (get size + tree)
+    for is_server in (True, False):
+        max_channel = 0
+        parsers = {}
+        for channel in proto.channels:
+            max_channel = max(max_channel, channel.value)
+
+            parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server))
+
+        write_get_channel_parser(writer, parsers, max_channel, is_server)
 
 def write_includes(writer):
     writer.newline()
-- 
2.1.0



More information about the Spice-devel mailing list