[Spice-devel] [PATCH v5 02/41] dissector: Generate some definition for dissector

Frediano Ziglio fziglio at redhat.com
Fri Aug 7 08:00:31 PDT 2015


Generate global definitions.
Generate function to registers various dissector components.
For the moment the field array is empty but we save some global to
be able to register new ones.
Add a base test for generated dissector.

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 Makefile.am                 |  2 +-
 codegen/Makefile.am         | 42 ++++++++++++++++++++++
 codegen/dissector_test.c    | 81 +++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 10 ++++++
 python_modules/dissector.py | 87 +++++++++++++++++++++++++++++++++++++++++++--
 spice_codegen.py            |  2 +-
 6 files changed, 219 insertions(+), 5 deletions(-)
 create mode 100644 codegen/Makefile.am
 create mode 100644 codegen/dissector_test.c

diff --git a/Makefile.am b/Makefile.am
index 1082bf2..595f24b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 NULL =
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = python_modules spice
+SUBDIRS = python_modules spice codegen
 
 codegendir = $(libdir)/spice-protocol
 dist_codegen_DATA =			\
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
new file mode 100644
index 0000000..e959783
--- /dev/null
+++ b/codegen/Makefile.am
@@ -0,0 +1,42 @@
+NULL =
+
+if WIRESHARK
+AM_CPPFLAGS =				\
+	-I$(top_srcdir)			\
+	$(WIRESHARK_CFLAGS)		\
+	$(GLIB2_CFLAGS)			\
+	$(NULL)
+
+dissector_test_LDADD =			\
+	$(GLIB2_LIBS)			\
+	$(NULL)
+
+MARSHALLERS_DEPS =					\
+	$(top_srcdir)/python_modules/__init__.py	\
+	$(top_srcdir)/python_modules/codegen.py		\
+	$(top_srcdir)/python_modules/demarshal.py	\
+	$(top_srcdir)/python_modules/marshal.py		\
+	$(top_srcdir)/python_modules/ptypes.py		\
+	$(top_srcdir)/python_modules/spice_parser.py	\
+	$(top_srcdir)/python_modules/dissector.py	\
+	$(top_srcdir)/spice_codegen.py			\
+	$(NULL)
+
+BUILT_SOURCES = test.h
+
+test.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS)
+	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-dissector --client $< $@ >/dev/null
+
+test.h: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS)
+	$(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-dissector --client $< --header $@ >/dev/null
+
+TESTS = dissector_test
+check_PROGRAMS = dissector_test
+
+dissector_test_SOURCES = dissector_test.c test.c test.h
+endif
+
+EXTRA_DIST =				\
+	$(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/codegen/dissector_test.c b/codegen/dissector_test.c
new file mode 100644
index 0000000..6189da0
--- /dev/null
+++ b/codegen/dissector_test.c
@@ -0,0 +1,81 @@
+#undef NDEBUG
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <epan/expert.h>
+
+#include <test.h>
+
+enum {
+	first_hf_registered = 0x10000,
+	first_ei_registered = 0x20000,
+};
+static int last_hf_registered = first_hf_registered - 1;
+static int last_ei_registered = first_ei_registered - 1;
+
+WS_DLL_PUBLIC void
+proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
+{
+	int i;
+	assert(num_records >= 0);
+	for (i = 0; i < num_records; ++i) {
+		assert(hf);
+		assert(hf[i].p_id);
+		assert(*hf[i].p_id == -1);
+		*hf[i].p_id = ++last_hf_registered;
+	}
+}
+
+WS_DLL_PUBLIC void
+expert_register_field_array(expert_module_t* module, ei_register_info *ei, const int num_records)
+{
+	int i;
+	assert(num_records >= 0);
+	for (i = 0; i < num_records; ++i) {
+		assert(ei && ei[i].ids->ei == -1);
+		ei[i].ids->ei = ++last_ei_registered;
+	}
+}
+
+static const struct option long_options[] = {
+	{ "help", 0, NULL, 'h' },
+};
+static const char options[] = "h";
+
+static void syntax(FILE *f, int exit_value)
+{
+	fprintf(f,
+		"Usage: dissector_test [OPTIONS]\n"
+		"\n"
+		"Options:\n"
+		"  -h, --help               Show this help\n"
+	);
+	exit(exit_value);
+}
+
+int main(int argc, char **argv)
+{
+	while (1) {
+		int option_index;
+		int opt = getopt_long(argc, argv, options, long_options, &option_index);
+		if (opt == -1)
+			break;
+
+		switch (opt) {
+		case 'h':
+			syntax(stdout, EXIT_SUCCESS);
+			break;
+		default:
+			syntax(stderr, EXIT_FAILURE);
+			break;
+		}
+	}
+
+	spice_register_fields(1, NULL);
+
+	return EXIT_SUCCESS;
+}
diff --git a/configure.ac b/configure.ac
index 2485489..715dc2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,9 +30,19 @@ if test "x$enable_code_generator" != "xno"; then
 fi
 AM_CONDITIONAL([ENABLE_CODEGEN], [test "x$enable_code_generator" != "xno"])
 
+AC_PROG_CC
+AM_PROG_CC_C_O
+
+PKG_CHECK_MODULES(WIRESHARK, wireshark,
+	[AM_CONDITIONAL(WIRESHARK, true)
+	PKG_CHECK_MODULES(GLIB2, glib-2.0)],
+	AM_CONDITIONAL(WIRESHARK, false)
+)
+
 AC_OUTPUT([
 Makefile
 spice-protocol.pc
 spice/Makefile
 python_modules/Makefile
+codegen/Makefile
 ])
diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index 90ba498..45f8737 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -1,14 +1,95 @@
 
 from . import codegen
+import re
+
+hf_writer = None
+hf_defs = None
+
+
+def write_parser_helpers(writer):
+    if writer.is_generated("helper", "demarshaller"):
+        return
+
+    writer.set_is_generated("helper", "demarshaller")
+
+    header = writer.header
+
+    header.writeln('#include <epan/packet.h>')
+    header.newline()
+
+    header.begin_block("typedef struct GlobalInfo")
+    header.variable_def("tvbuff_t *", "tvb")
+    header.variable_def("packet_info *", "pinfo")
+    header.variable_def("proto_item *", "msgtype_item")
+    header.variable_def("guint32", "message_offset")
+    header.variable_def("guint32", "message_end")
+    header.end_block(newline=False)
+    header.writeln(' GlobalInfo;')
+
+    header.newline()
+    header.statement('typedef guint32 (*spice_dissect_func_t)(guint16 message_type, GlobalInfo *glb, proto_tree *tree, guint32 offset)')
+
+    header.newline()
+    header.statement('void spice_register_fields(int proto, expert_module_t* expert_proto)')
+    header.statement('spice_dissect_func_t spice_client_channel_get_dissect(guint8 channel)')
+    header.statement('spice_dissect_func_t spice_server_channel_get_dissect(guint8 channel)')
+
+    writer = writer.function_helper()
+
+    writer.newline()
+    writer.statement('typedef guint32 (*parse_msg_func_t)(GlobalInfo *glb, proto_tree *tree, guint32 offset)')
+    writer.newline()
+    writer.statement('static expert_field ei_spice_unknown_message = EI_INIT')
+
+    writer.newline()
+    writer.writeln('#ifndef _U_')
+    writer.writeln('#define _U_')
+    writer.writeln('#endif')
+    writer.newline()
+
+
+def write_protocol_definitions(writer):
+    global hf_defs
+
+    writer.newline()
+    writer.function('spice_register_fields', 'void', 'int proto, expert_module_t* expert_proto')
+
+    writer.write("static hf_register_info hf[] = ")
+    writer.begin_block()
+    hf_defs = writer.get_subwriter()
+    writer.end_block(semicolon = True)
+    writer.newline()
+
+    writer.write('static ei_register_info ei[] =')
+    writer.begin_block()
+    writer.writeln('{ &ei_spice_unknown_message, { "spice.unknown_message", PI_UNDECODED, PI_WARN, "Unknown message - cannot dissect", EXPFILL }},')
+    writer.end_block(semicolon = True)
+    writer.newline()
+
+    writer.statement('proto_register_field_array(proto, hf, array_length(hf))')
+    writer.statement('expert_register_field_array(expert_proto, ei, array_length(ei))')
+    writer.end_block()
+
 
 def write_protocol_parser(writer, proto):
-    pass
+    global hf_writer
+
+    write_parser_helpers(writer)
+
+    # put fields declaration first
+    hf_writer = writer.get_subwriter()
+
+    # put fields definition at last
+    write_protocol_definitions(writer)
 
-def write_includes(writer):
+def write_includes(writer, dest_file):
+    header_name = re.sub(r'\.(c|cpp|cc|cxx|C)$', '.h', dest_file)
+    if header_name == dest_file:
+        header_name += '.h'
     writer.newline()
-    writer.writeln('#include <epan/packet.h>')
     writer.writeln('#include <epan/conversation.h>')
     writer.writeln('#include <epan/expert.h>')
     writer.newline()
+    writer.writeln('#include "%s"' % header_name)
     writer.writeln('#include "packet-spice.h"')
     writer.newline()
diff --git a/spice_codegen.py b/spice_codegen.py
index 4f0d5cf..3646a7e 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -224,7 +224,7 @@ if options.generate_dissector:
     if options.generate_demarshallers:
         print >> sys.stderr, "You can't specify --generate-demarshallers with --generate-dissector"
         sys.exit(1)
-    dissector.write_includes(writer)
+    dissector.write_includes(writer, dest_file)
     dissector.write_protocol_parser(writer, proto)
 
 if options.generate_demarshallers:
-- 
2.1.0



More information about the Spice-devel mailing list