[Spice-devel] [PATCH v6 03/42] dissector: Generate some definition for dissector

Frediano Ziglio fziglio at redhat.com
Thu Aug 13 06:11:42 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 +-
 configure.ac                | 10 +++++
 python_modules/dissector.py | 89 +++++++++++++++++++++++++++++++++++++++++++--
 spice_codegen.py            |  2 +-
 tests/Makefile.am           | 42 +++++++++++++++++++++
 tests/dissector_test.c      | 81 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 221 insertions(+), 5 deletions(-)
 create mode 100644 tests/Makefile.am
 create mode 100644 tests/dissector_test.c

diff --git a/Makefile.am b/Makefile.am
index 53e87be..f011fa6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 NULL =
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = python_modules spice
+SUBDIRS = python_modules spice tests
 
 codegendir = $(libdir)/spice-protocol
 dist_codegen_DATA =			\
diff --git a/configure.ac b/configure.ac
index 2485489..d0acfac 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
+tests/Makefile
 ])
diff --git a/python_modules/dissector.py b/python_modules/dissector.py
index 90ba498..3e9835f 100644
--- a/python_modules/dissector.py
+++ b/python_modules/dissector.py
@@ -1,14 +1,97 @@
 
 from . import codegen
+import re
+
+dissector_short_name = 'spice2'
+
+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, { "%s.unknown_message", PI_UNDECODED, PI_WARN, "Unknown message - cannot dissect", EXPFILL }},' % dissector_short_name)
+    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 0a6cefc..34458ff 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -230,7 +230,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:
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..e959783
--- /dev/null
+++ b/tests/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/tests/dissector_test.c b/tests/dissector_test.c
new file mode 100644
index 0000000..6189da0
--- /dev/null
+++ b/tests/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;
+}
-- 
2.4.3



More information about the Spice-devel mailing list