'skeleton' in the subject. On Tue, Jul 21, 2015 at 05:45:45PM +0100, Frediano Ziglio wrote: > Messages are not generated as stub. > Code partially from demarshaller. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > codegen/Makefile.am | 3 +- > codegen/check_dissector | 13 +++++ > codegen/dissector_test.c | 54 ++++++++++++++++- > python_modules/dissector.py | 138 +++++++++++++++++++++++++++++++++++++++++++- > 4 files changed, 203 insertions(+), 5 deletions(-) > create mode 100755 codegen/check_dissector > > diff --git a/codegen/Makefile.am b/codegen/Makefile.am > index 129543c..b147b85 100644 > --- a/codegen/Makefile.am > +++ b/codegen/Makefile.am > @@ -29,12 +29,13 @@ test.c: $(top_srcdir)/spice.proto $(MARSHALLERS_DEPS) > 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 > +TESTS = check_dissector > check_PROGRAMS = dissector_test > > dissector_test_SOURCES = dissector_test.c test.c test.h > > EXTRA_DIST = \ > + check_dissector \ > $(NULL) > > -include $(top_srcdir)/git.mk > diff --git a/codegen/check_dissector b/codegen/check_dissector > new file mode 100755 > index 0000000..f1444a2 > --- /dev/null > +++ b/codegen/check_dissector > @@ -0,0 +1,13 @@ > +#!/bin/bash > +set -e > + > +error() { > + echo "$*" >&2 > + exit 1 > +} > + > +./dissector_test 1 100 > +if ./dissector_test 1 99; then > + error "This test should fail" > +fi > +exit 0 > diff --git a/codegen/dissector_test.c b/codegen/dissector_test.c > index 3212655..25a33b5 100644 > --- a/codegen/dissector_test.c > +++ b/codegen/dissector_test.c > @@ -4,6 +4,7 @@ > #include <stdlib.h> > #include <unistd.h> > #include <getopt.h> > +#include <stdbool.h> > #include <assert.h> > > #include <epan/expert.h> > @@ -18,6 +19,7 @@ enum { > static int last_hf_registered = first_hf_registered - 1; > static int last_ei_registered = first_ei_registered - 1; > static int last_tree_registered = first_tree_registered - 1; > +static bool got_error = false; > > WS_DLL_PUBLIC void > proto_register_field_array(const int parent, hf_register_info *hf, const int num_records) > @@ -54,24 +56,46 @@ expert_register_field_array(expert_module_t* module, ei_register_info *ei, const > } > } > > +WS_DLL_PUBLIC void > +expert_add_info_format(packet_info *pinfo, proto_item *pi, expert_field *eiindex, > + const char *format, ...) > +{ > + assert(format); > + got_error = true; > + if (!pi) > + return; > +} > + > static const struct option long_options[] = { > { "help", 0, NULL, 'h' }, > + { "server", 0, NULL, 's' }, > + { "client", 0, NULL, 'c' }, > }; > -static const char options[] = "h"; > +static const char options[] = "hsc"; > > static void syntax(FILE *f, int exit_value) > { > fprintf(f, > - "Usage: dissector_test [OPTIONS]\n" > + "Usage: dissector_test [OPTIONS] CHANNEL MESSAGE_TYPE\n" > "\n" > "Options:\n" > " -h, --help Show this help\n" > + " -s, --server Process server messages (default)\n" > + " -c, --client Process client messages\n" > ); > exit(exit_value); > } > > int main(int argc, char **argv) > { > + int channel, message_type; > + GlobalInfo glb; > + proto_tree tree; > + spice_dissect_func_t (*msg_func)(guint8 channel); > + spice_dissect_func_t channel_func = NULL; > + > + msg_func = spice_server_channel_get_dissect; > + > while (1) { > int option_index; > int opt = getopt_long(argc, argv, options, long_options, &option_index); > @@ -82,13 +106,37 @@ int main(int argc, char **argv) > case 'h': > syntax(stdout, EXIT_SUCCESS); > break; > + case 's': > + msg_func = spice_server_channel_get_dissect; > + break; > + case 'c': > + msg_func = spice_client_channel_get_dissect; > + break; > default: > syntax(stderr, EXIT_FAILURE); > break; > } > } > + if (optind + 2 > argc) > + syntax(stderr, EXIT_FAILURE); > + > + channel = strtol(argv[optind++], NULL, 0); > + message_type = strtol(argv[optind++], NULL, 0); > > spice_register_fields(1, NULL); > > - return EXIT_SUCCESS; > + memset(&glb, 0, sizeof(glb)); > + glb.tvb = NULL; > + glb.message_offset = 0; > + glb.message_end = 0; > + > + channel_func = msg_func(channel); > + assert(channel_func); > + > + memset(&tree, 0, sizeof(tree)); > + > + /* TODO check offset ?? */ > + channel_func(message_type, &glb, &tree, 0); > + > + return got_error ? EXIT_FAILURE : EXIT_SUCCESS; > } > diff --git a/python_modules/dissector.py b/python_modules/dissector.py > index f9ad08a..af0494c 100644 > --- a/python_modules/dissector.py > +++ b/python_modules/dissector.py > @@ -1,4 +1,5 @@ > > +from . import ptypes > from . import codegen > import re > > @@ -65,6 +66,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 > @@ -125,8 +244,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, dest_file): > header_name = re.sub(r'\.(c|cpp|cc|cxx|C)$', '.h', dest_file) > -- > 2.1.0 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
pgpQkFAARLEqX.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel